Ignore:
Timestamp:
May 13, 2016, 1:19:55 AM (7 years ago)
Author:
roman
Message:

Checking MF_MPEG4SINK_MOOV_BEFORE_MDAT

Location:
trunk/Utilities/MediaFoundation/SimultaneousCapture
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Utilities/MediaFoundation/SimultaneousCapture/Module.h

    r630 r631  
    435435        };
    436436
     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
    437800        template <typename CVideoMediaType, typename CAudioMediaType>
    438801        class CSessionT
     
    536899                                m_sPath = CreateOutputPath();
    537900                        // 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
    539922                        DWORD nVideoWriterStreamIndex, nAudioWriterStreamIndex;
    540923                        #pragma region H.264 Video
     
    554937                                pVideoMediaType[MF_MT_PIXEL_ASPECT_RATIO] = m_VideoMediaType.m_pMediaType.GetUINT64(MF_MT_PIXEL_ASPECT_RATIO);
    555938                        }
    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                        }
    558944                        #pragma endregion
    559945                        #pragma region AAC Audio
     
    569955                        pAudioMediaType[MF_MT_AUDIO_NUM_CHANNELS] = (UINT32) m_AudioMediaType.m_pMediaType.GetUINT32(MF_MT_AUDIO_NUM_CHANNELS);
    570956                        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                        }
    573962                        #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
    574965                        _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                        }
    577984                }
    578985                HANDLE GetSampleAvailabilityEvent() const
Note: See TracChangeset for help on using the changeset viewer.