Changeset 631 for trunk/Utilities/MediaFoundation/SimultaneousCapture
- Timestamp:
- May 13, 2016, 1:19:55 AM (7 years ago)
- Location:
- trunk/Utilities/MediaFoundation/SimultaneousCapture
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Utilities/MediaFoundation/SimultaneousCapture/Module.h
r630 r631 435 435 }; 436 436 437 //////////////////////////////////////////////////////// 438 // CFileByteStream 439 440 class ATL_NO_VTABLE CFileByteStream : 441 public CComObjectRootEx<CComMultiThreadModelNoCS>, 442 public IMFByteStream, 443 public IMFSampleOutputStream 444 { 445 public: 446 447 DECLARE_QI_TRACE(CFileByteStream) 448 449 BEGIN_COM_MAP(CFileByteStream) 450 COM_INTERFACE_ENTRY(IMFByteStream) 451 //COM_INTERFACE_ENTRY(IMFSampleOutputStream) 452 END_COM_MAP() 453 454 public: 455 456 //////////////////////////////////////////////////////// 457 // CWriteObject 458 459 class ATL_NO_VTABLE __declspec(uuid("{C0368834-0679-4720-A8C4-E0A68E4F2750}")) CWriteObject : 460 public CComObjectRootEx<CComMultiThreadModelNoCS>, 461 public IUnknown 462 { 463 public: 464 465 //DECLARE_QI_TRACE(CWriteObject) 466 467 BEGIN_COM_MAP(CWriteObject) 468 COM_INTERFACE_ENTRY_IID(__uuidof(CWriteObject), CWriteObject) 469 END_COM_MAP() 470 471 public: 472 ULONG m_nDataSize; 473 474 public: 475 // CWriteObject 476 CWriteObject() : 477 m_nDataSize(0) 478 { 479 _Z5_THIS(); 480 } 481 ~CWriteObject() 482 { 483 _Z5_THIS(); 484 } 485 }; 486 487 private: 488 mutable CRoCriticalSection m_DataCriticalSection; 489 CAtlFile m_File; 490 CHeapPtr<BYTE> m_pnData; 491 ULONGLONG m_nDataCapacity; 492 ULONGLONG m_nDataSize; 493 ULONGLONG m_nDataPosition; 494 495 VOID SetDataCapacity(ULONGLONG nDataCapacity) 496 { 497 if(nDataCapacity <= m_nDataCapacity) 498 return; 499 static const SIZE_T g_nDataGranularity = 1 << 20; // 1 MB 500 _A(!(g_nDataGranularity & (g_nDataGranularity - 1))); 501 nDataCapacity += (g_nDataGranularity - 1); 502 nDataCapacity &= (ULONGLONG) ~(g_nDataGranularity - 1); 503 __D(m_pnData.Reallocate((SIZE_T) nDataCapacity), E_OUTOFMEMORY); 504 m_nDataCapacity = nDataCapacity; 505 } 506 507 public: 508 // CFileByteStream 509 CFileByteStream() : 510 m_nDataCapacity(0), 511 m_nDataSize(0), 512 m_nDataPosition(0) 513 { 514 _Z4_THIS(); 515 } 516 ~CFileByteStream() 517 { 518 _Z4_THIS(); 519 } 520 VOID Initialize(LPCTSTR pszPath) 521 { 522 //CRoCriticalSectionLock DataLock(m_DataCriticalSection); 523 __C(m_File.Create(pszPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, CREATE_ALWAYS)); 524 } 525 526 // IMFByteStream 527 STDMETHOD(GetCapabilities)(DWORD* pnCapabilities) override 528 { 529 _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this); 530 _ATLTRY 531 { 532 __D(pnCapabilities, E_POINTER); 533 //CRoCriticalSectionLock DataLock(m_DataCriticalSection); 534 *pnCapabilities = MFBYTESTREAM_IS_READABLE | MFBYTESTREAM_IS_WRITABLE | MFBYTESTREAM_IS_SEEKABLE | MFBYTESTREAM_DOES_NOT_USE_NETWORK; 535 } 536 _ATLCATCH(Exception) 537 { 538 _C(Exception); 539 } 540 return S_OK; 541 } 542 STDMETHOD(GetLength)(QWORD* pnLength) override 543 { 544 _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this); 545 _ATLTRY 546 { 547 __D(pnLength, E_POINTER); 548 CRoCriticalSectionLock DataLock(m_DataCriticalSection); 549 *pnLength = m_nDataSize; 550 } 551 _ATLCATCH(Exception) 552 { 553 _C(Exception); 554 } 555 return S_OK; 556 } 557 STDMETHOD(SetLength)(QWORD nLength) override 558 { 559 _Z4(atlTraceCOM, 4, _T("this 0x%p, nLength %I64d\n"), this, nLength); 560 _ATLTRY 561 { 562 CRoCriticalSectionLock DataLock(m_DataCriticalSection); 563 SetDataCapacity(nLength); 564 m_nDataSize = nLength; 565 if(m_nDataPosition > m_nDataSize) 566 m_nDataPosition = m_nDataSize; 567 } 568 _ATLCATCH(Exception) 569 { 570 _C(Exception); 571 } 572 return S_OK; 573 } 574 STDMETHOD(GetCurrentPosition)(QWORD* pnPosition) override 575 { 576 _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this); 577 _ATLTRY 578 { 579 __D(pnPosition, E_POINTER); 580 CRoCriticalSectionLock DataLock(m_DataCriticalSection); 581 *pnPosition = m_nDataPosition; 582 } 583 _ATLCATCH(Exception) 584 { 585 _C(Exception); 586 } 587 return S_OK; 588 } 589 STDMETHOD(SetCurrentPosition)(QWORD nPosition) override 590 { 591 _Z4(atlTraceCOM, 4, _T("this 0x%p, nPosition %I64d\n"), this, nPosition); 592 _ATLTRY 593 { 594 CRoCriticalSectionLock DataLock(m_DataCriticalSection); 595 __D(nPosition <= m_nDataSize, E_INVALIDARG); 596 m_nDataPosition = nPosition; 597 } 598 _ATLCATCH(Exception) 599 { 600 _C(Exception); 601 } 602 return S_OK; 603 } 604 STDMETHOD(IsEndOfStream)(BOOL* pbEndOfStream) override 605 { 606 _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this); 607 _ATLTRY 608 { 609 __D(pbEndOfStream, E_POINTER); 610 CRoCriticalSectionLock DataLock(m_DataCriticalSection); 611 *pbEndOfStream = m_nDataPosition >= m_nDataSize; 612 } 613 _ATLCATCH(Exception) 614 { 615 _C(Exception); 616 } 617 return S_OK; 618 } 619 STDMETHOD(Read)(BYTE* pnData, ULONG nDataCapacity, ULONG* pnDataSize) override 620 { 621 _Z4(atlTraceCOM, 4, _T("this 0x%p, nDataCapacity %d\n"), this, nDataCapacity); 622 _ATLTRY 623 { 624 // TODO: ... 625 _C(E_NOTIMPL); 626 } 627 _ATLCATCH(Exception) 628 { 629 _C(Exception); 630 } 631 return S_OK; 632 } 633 STDMETHOD(BeginRead)(BYTE* pnData, ULONG nDataCapacity, IMFAsyncCallback* pCallback, IUnknown* pState) override 634 { 635 _Z4(atlTraceCOM, 4, _T("this 0x%p, nDataCapacity %d\n"), this, nDataCapacity); 636 _ATLTRY 637 { 638 // TODO: ... 639 _C(E_NOTIMPL); 640 } 641 _ATLCATCH(Exception) 642 { 643 _C(Exception); 644 } 645 return S_OK; 646 } 647 STDMETHOD(EndRead)(IMFAsyncResult* pResult, ULONG* pnDataSize) override 648 { 649 _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this); 650 _ATLTRY 651 { 652 // TODO: ... 653 _C(E_NOTIMPL); 654 } 655 _ATLCATCH(Exception) 656 { 657 _C(Exception); 658 } 659 return S_OK; 660 } 661 STDMETHOD(Write)(const BYTE* pnData, ULONG nDataSize, ULONG* pnWriteDataSize) override 662 { 663 _Z4(atlTraceCOM, 4, _T("this 0x%p, nDataSize %d\n"), this, nDataSize); 664 _ATLTRY 665 { 666 __D(pnData || !nDataSize, E_INVALIDARG); 667 __D(pnWriteDataSize, E_POINTER); 668 CRoCriticalSectionLock DataLock(m_DataCriticalSection); 669 if(nDataSize) 670 { 671 SetDataCapacity(m_nDataPosition + nDataSize); 672 memcpy(m_pnData + (SIZE_T) m_nDataPosition, pnData, nDataSize); 673 m_nDataPosition += nDataSize; 674 if(m_nDataPosition > m_nDataSize) 675 m_nDataSize = m_nDataPosition; 676 } 677 *pnWriteDataSize = nDataSize; 678 } 679 _ATLCATCH(Exception) 680 { 681 _C(Exception); 682 } 683 return S_OK; 684 } 685 STDMETHOD(BeginWrite)(const BYTE* pnData, ULONG nDataSize, IMFAsyncCallback* pCallback, IUnknown* pState) override 686 { 687 _Z5(atlTraceCOM, 5, _T("this 0x%p, nDataSize %d, pCallback 0x%p, pState 0x%p\n"), this, nDataSize, pCallback, pState); 688 _ATLTRY 689 { 690 CLocalObjectPtr<CWriteObject> pWriteObject; 691 __C(Write(pnData, nDataSize, &pWriteObject->m_nDataSize)); 692 CComPtr<IMFAsyncResult> pAsyncResult; 693 __C(MFCreateAsyncResult(pWriteObject, pCallback, pState, &pAsyncResult)); 694 __C(pCallback->Invoke(pAsyncResult)); 695 } 696 _ATLCATCH(Exception) 697 { 698 _C(Exception); 699 } 700 return S_OK; 701 } 702 STDMETHOD(EndWrite)(IMFAsyncResult* pResult, ULONG* pnDataSize) override 703 { 704 _Z5(atlTraceCOM, 5, _T("this 0x%p, pResult 0x%p\n"), this, pResult); 705 _ATLTRY 706 { 707 __D(pResult, E_INVALIDARG); 708 __D(pnDataSize, E_POINTER); 709 CComPtr<IUnknown> pObjectUnknown; 710 __C(pResult->GetObject(&pObjectUnknown)); 711 CWriteObject* pWriteObject = static_cast<CWriteObject*>((IUnknown*) pObjectUnknown); 712 _A(pWriteObject == (CWriteObject*) CComQIPtr<CWriteObject>(pObjectUnknown)); 713 *pnDataSize = pWriteObject->m_nDataSize; 714 } 715 _ATLCATCH(Exception) 716 { 717 _C(Exception); 718 } 719 return S_OK; 720 } 721 STDMETHOD(Seek)(MFBYTESTREAM_SEEK_ORIGIN Origin, LONGLONG nOffset, DWORD nFlags, QWORD* pnPosition) override 722 { 723 _Z4(atlTraceCOM, 4, _T("this 0x%p, Origin %d, nOffset %I64d, nFlags 0x%X\n"), this, Origin, nOffset, nFlags); 724 _ATLTRY 725 { 726 // TODO: ... 727 _C(E_NOTIMPL); 728 } 729 _ATLCATCH(Exception) 730 { 731 _C(Exception); 732 } 733 return S_OK; 734 } 735 STDMETHOD(Flush)() override 736 { 737 _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this); 738 _ATLTRY 739 { 740 // TODO: ... 741 } 742 _ATLCATCH(Exception) 743 { 744 _C(Exception); 745 } 746 return S_OK; 747 } 748 STDMETHOD(Close)() override 749 { 750 _Z4(atlTraceCOM, 4, _T("this 0x%p\n"), this); 751 _ATLTRY 752 { 753 CRoCriticalSectionLock DataLock(m_DataCriticalSection); 754 __D(m_File, E_UNNAMED); 755 __C(m_File.Write(m_pnData, (DWORD) m_nDataSize)); 756 m_File.Close(); 757 } 758 _ATLCATCH(Exception) 759 { 760 _C(Exception); 761 } 762 return S_OK; 763 } 764 765 // IMFSampleOutputStream 766 STDMETHOD(BeginWriteSample)(IMFSample* pSample, IMFAsyncCallback* pCallback, IUnknown* pState) override 767 { 768 _Z4(atlTraceCOM, 4, _T("this 0x%p, pSample 0x%p, pCallback 0x%p, pState 0x%p\n"), this, pSample, pCallback, pState); 769 _ATLTRY 770 { 771 // TODO: ... 772 _C(E_NOTIMPL); 773 } 774 _ATLCATCH(Exception) 775 { 776 _C(Exception); 777 } 778 return S_OK; 779 } 780 STDMETHOD(EndWriteSample)(IMFAsyncResult* pResult) override 781 { 782 _Z4(atlTraceCOM, 4, _T("this 0x%p, pResult 0x%p\n"), this, pResult); 783 _ATLTRY 784 { 785 // TODO: ... 786 _C(E_NOTIMPL); 787 } 788 _ATLCATCH(Exception) 789 { 790 _C(Exception); 791 } 792 return S_OK; 793 } 794 //STDMETHOD(Close)() override 795 }; 796 797 //////////////////////////////////////////////////////// 798 // CSessionT 799 437 800 template <typename CVideoMediaType, typename CAudioMediaType> 438 801 class CSessionT … … 536 899 m_sPath = CreateOutputPath(); 537 900 // NOTE: MFCreateSinkWriterFromURL https://msdn.microsoft.com/en-us/library/windows/desktop/dd388105 538 __C(MFCreateSinkWriterFromURL(CT2CW(m_sPath), NULL, NULL, &m_pSinkWriter)); 901 CComPtr<IMFByteStream> pByteStream; 902 MF::CAttributes pSinkAttributes; 903 #if FALSE 904 CObjectPtr<CFileByteStream> pFileByteStream; 905 pFileByteStream.Construct()->Initialize(m_sPath); 906 pByteStream = pFileByteStream; 907 // WARN: It looks like this cannot have effect when used like this; the attribute is apparently NOT working the supposed way that 908 // media sink somehow sees it and update the media file. I suppose instead it is rather Transcode API attribute (despite the 909 // naming) and is handled through API patch that internally applies additional re-muxing behind the scenes... 910 pSinkAttributes.Create(1); 911 pSinkAttributes[MF_MPEG4SINK_MOOV_BEFORE_MDAT] = (UINT32) 1; 912 #if TRUE 913 CObjectPtr<MF::Private::CAttributes> pPrivateAttributes; 914 pPrivateAttributes.Construct()->Initialize(pSinkAttributes); 915 pSinkAttributes.m_p = (IMFAttributes*) pPrivateAttributes; 916 #endif 917 // NOTE: This is a development code path, see if(m_pSinkWriter) workaround below 918 //__C(MFCreateSinkWriterFromURL(CT2CW(m_sPath), pByteStream, pSinkAttributes, &m_pSinkWriter)); 919 #else 920 __C(MFCreateSinkWriterFromURL(CT2CW(m_sPath), pByteStream, pSinkAttributes, &m_pSinkWriter)); 921 #endif 539 922 DWORD nVideoWriterStreamIndex, nAudioWriterStreamIndex; 540 923 #pragma region H.264 Video … … 554 937 pVideoMediaType[MF_MT_PIXEL_ASPECT_RATIO] = m_VideoMediaType.m_pMediaType.GetUINT64(MF_MT_PIXEL_ASPECT_RATIO); 555 938 } 556 __C(m_pSinkWriter->AddStream(pVideoMediaType, &nVideoWriterStreamIndex)); 557 __C(m_pSinkWriter->SetInputMediaType(nVideoWriterStreamIndex, m_VideoMediaType.m_pMediaType, NULL)); 939 if(m_pSinkWriter) 940 { 941 __C(m_pSinkWriter->AddStream(pVideoMediaType, &nVideoWriterStreamIndex)); 942 __C(m_pSinkWriter->SetInputMediaType(nVideoWriterStreamIndex, m_VideoMediaType.m_pMediaType, NULL)); 943 } 558 944 #pragma endregion 559 945 #pragma region AAC Audio … … 569 955 pAudioMediaType[MF_MT_AUDIO_NUM_CHANNELS] = (UINT32) m_AudioMediaType.m_pMediaType.GetUINT32(MF_MT_AUDIO_NUM_CHANNELS); 570 956 pAudioMediaType[MF_MT_AUDIO_AVG_BYTES_PER_SECOND] = (UINT32) 20000; 571 __C(m_pSinkWriter->AddStream(pAudioMediaType, &nAudioWriterStreamIndex)); 572 __C(m_pSinkWriter->SetInputMediaType(nAudioWriterStreamIndex, m_AudioMediaType.m_pMediaType, NULL)); 957 if(m_pSinkWriter) 958 { 959 __C(m_pSinkWriter->AddStream(pAudioMediaType, &nAudioWriterStreamIndex)); 960 __C(m_pSinkWriter->SetInputMediaType(nAudioWriterStreamIndex, m_AudioMediaType.m_pMediaType, NULL)); 961 } 573 962 #pragma endregion 963 // NOTE: See IMFSinkWriterEx::GetTransformForStream https://msdn.microsoft.com/en-us/library/windows/desktop/hh448061 964 // which might possibly indicate internal MFTs such as, for example, format conversion and audio encoder for AAC audio 574 965 _A(m_StreamIndexMap.IsEmpty()); 575 m_StreamIndexMap[m_VideoMediaType.m_nStreamIndex] = nVideoWriterStreamIndex; 576 m_StreamIndexMap[m_AudioMediaType.m_nStreamIndex] = nAudioWriterStreamIndex; 966 if(m_pSinkWriter) 967 { 968 m_StreamIndexMap[m_VideoMediaType.m_nStreamIndex] = nVideoWriterStreamIndex; 969 m_StreamIndexMap[m_AudioMediaType.m_nStreamIndex] = nAudioWriterStreamIndex; 970 } else 971 { 972 // TODO: Add audio support 973 pAudioMediaType.Release(); 974 CComPtr<IMFMediaSink> pMediaSink; 975 __C(MFCreateMPEG4MediaSink(pByteStream, pVideoMediaType, pAudioMediaType, &pMediaSink)); 976 __C(MFCreateSinkWriterFromMediaSink(pMediaSink, pSinkAttributes, &m_pSinkWriter)); 977 nVideoWriterStreamIndex = 0; 978 // __C(m_pSinkWriter->AddStream(pVideoMediaType, &nVideoWriterStreamIndex)); // MF_E_STREAMSINKS_FIXED 979 __C(m_pSinkWriter->SetInputMediaType(nVideoWriterStreamIndex, m_VideoMediaType.m_pMediaType, NULL)); 980 // //__C(m_pSinkWriter->AddStream(pAudioMediaType, &nAudioWriterStreamIndex)); 981 // //__C(m_pSinkWriter->SetInputMediaType(nAudioWriterStreamIndex, m_AudioMediaType.m_pMediaType, NULL)); 982 m_StreamIndexMap[m_VideoMediaType.m_nStreamIndex] = nVideoWriterStreamIndex; 983 } 577 984 } 578 985 HANDLE GetSampleAvailabilityEvent() const
Note: See TracChangeset
for help on using the changeset viewer.