Changeset 593


Ignore:
Timestamp:
Feb 27, 2016, 2:31:34 PM (7 years ago)
Author:
roman
Message:
 
Location:
trunk/Utilities/FFmpeg/DecodeMpeg4Video02
Files:
2 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/Utilities/FFmpeg/DecodeMpeg4Video02/Application.cpp

    r592 r593  
    4646
    4747private:
     48        BOOL m_bAnnexB;
    4849
    4950public:
    5051// CModule
     52        CModule()
     53        {
     54                m_bAnnexB = FALSE;
     55        }
     56        HRESULT PreMessageLoop(INT nShowCommand)
     57        {
     58                _V(__super::PreMessageLoop(nShowCommand));
     59                return S_OK;
     60        }
    5161        static BOOL ReadFileData(LPCTSTR pszPath, CHeapPtr<BYTE>& pnData, SIZE_T& nDataSize)
    5262        {
     
    6777                return ReadFileData(pszPath, Blob.m_pnData, Blob.m_nDataSize);
    6878        }
    69         HRESULT PreMessageLoop(INT nShowCommand)
    70         {
    71                 _V(__super::PreMessageLoop(nShowCommand));
    72                 return S_OK;
     79        template <typename LENGTH>
     80        static SIZE_T CopyNalUnits(const BYTE* pnSourceData, SIZE_T nSourceDataSize, BYTE* pnDestinationData, SIZE_T nDestinationDataCapacity, BOOL bForceLongStartCode = FALSE)
     81        {
     82                _A(sizeof (LENGTH) == 2 || sizeof (LENGTH) == 4);
     83                BYTE* pnDestinationDataPointer = pnDestinationData;
     84                for(; nSourceDataSize; )
     85                {
     86                        const SIZE_T nUnitDataSize = (typename LENGTH::CBase) *((const LENGTH*) pnSourceData);
     87                        __D(sizeof (LENGTH) + nUnitDataSize <= nSourceDataSize, HRESULT_FROM_WIN32(ERROR_INVALID_DATA));
     88                        __D((SIZE_T) (pnDestinationDataPointer + 4 + nUnitDataSize - pnDestinationData) <= nDestinationDataCapacity, HRESULT_FROM_WIN32(ERROR_INSUFFICIENT_BUFFER));
     89                        pnSourceData += sizeof (LENGTH);
     90                        nSourceDataSize -= sizeof (LENGTH);
     91                        static const BYTE g_pnStartCode[] = { 0x00, 0x00, 0x00, 0x01 };
     92                        BOOL bLongStartCode = FALSE;
     93                        if(!bForceLongStartCode)
     94                        {
     95                                if(nUnitDataSize)
     96                                {
     97                                        const UINT nNalUnitType = *pnSourceData & 0x1F;
     98                                        if(nNalUnitType >= 6 && nNalUnitType <= 9) // SEI, SPS, PPS, Access Unit Delimiter
     99                                                bLongStartCode = TRUE;
     100                                }
     101                        } else
     102                                bLongStartCode = TRUE;
     103                        SIZE_T nStartCodeSize = sizeof g_pnStartCode;
     104                        if(!bLongStartCode)
     105                        {
     106                                memcpy(pnDestinationDataPointer, g_pnStartCode + 1, sizeof g_pnStartCode - 1);
     107                                nStartCodeSize--;
     108                        } else
     109                                memcpy(pnDestinationDataPointer, g_pnStartCode, sizeof g_pnStartCode);
     110                        pnDestinationDataPointer += nStartCodeSize;
     111                        memcpy(pnDestinationDataPointer, pnSourceData, nUnitDataSize);
     112                        pnSourceData += nUnitDataSize;
     113                        nSourceDataSize -= nUnitDataSize;
     114                        pnDestinationDataPointer += nUnitDataSize;
     115                }
     116                return pnDestinationDataPointer - pnDestinationData;
    73117        }
    74118        static INT CompareMediaSampleFileNames(LPCTSTR pszNameA, LPCTSTR pszNameB, INT)
     
    92136        {
    93137                CAvPacketT<FALSE> AvPacket(Blob.m_pnData, Blob.m_nDataSize);
     138                CBlob LocalBlob;
     139                if(m_bAnnexB)
     140                {
     141                        SIZE_T nDataCapacity = 1024 + Blob.m_nDataSize + Blob.m_nDataSize / 8;
     142                        __D(LocalBlob.m_pnData.Allocate(nDataCapacity), E_OUTOFMEMORY);
     143                        LocalBlob.m_nDataSize = CopyNalUnits<NUINT32>(Blob.m_pnData, Blob.m_nDataSize, LocalBlob.m_pnData, nDataCapacity);
     144                        _tprintf(_T("%d Annex B bytes from %d bytes\n"), LocalBlob.m_nDataSize, Blob.m_nDataSize);
     145                        AvPacket.data = LocalBlob.m_pnData;
     146                        AvPacket.size = (INT) LocalBlob.m_nDataSize;
     147                }
    94148                AvPacket.flags = 0; //AV_PKT_FLAG_KEY;
    95149                AvPacket.dts = AV_NOPTS_VALUE;
     
    97151                SIZE_T nDecodeDataSize;
    98152                const BOOL bFrameAvailable = pAvCodecContext.DecodeVideo(pAvFrame, &AvPacket, nDecodeDataSize);
    99                 _A(nDecodeDataSize == Blob.m_nDataSize);
     153                _A(nDecodeDataSize == (SIZE_T) AvPacket.size);
    100154                if(bFrameAvailable)
    101155                        ProcessFrame(pAvFrame);
     
    125179                static LPCTSTR g_pszDirectory =
    126180                        _T("D:\\Projects\\Alax.Info\\Repository-Private\\Utilities\\DirectShow\\H.264\\tiny.mp4 NAL Units");
    127                 static ULONG g_nFrameTime = 250;
     181                m_bAnnexB = TRUE;
     182                if(m_bAnnexB)
     183                        _tprintf(_T("Using H.264 Annex B\n"));
    128184                #pragma region Extra Data
    129                 CBlob AvcDecoderConfigurationRecordBlob;
    130                 {
    131                         CRoListT<CBlob> BlobList;
    132                         CRoArrayT<CBlob*> SpsBlobList, PpsBlobList;
    133                         for(UINT nIndex = 0; ; nIndex++)
     185                if(!m_bAnnexB)
     186                {
     187                        CBlob AvcDecoderConfigurationRecordBlob;
    134188                        {
    135                                 // NOTE: Naming sample: MediaType_00
    136                                 const CString sName = AtlFormatString(_T("MediaType_%02d"), nIndex);
    137                                 CPath sPath = Combine(g_pszDirectory, sName);
    138                                 if(!sPath.FileExists())
    139                                         break;
    140                                 CBlob& Blob = BlobList.GetAt(BlobList.AddTail());
    141                                 _W(ReadFileData(sPath, Blob));
    142                                 _tprintf(_T("Read %d bytes from %s\n"), Blob.m_nDataSize, sName);
    143                                 if(Blob.m_nDataSize < 1)
    144                                         continue;
    145                                 const UINT nNalUnitType = Blob.m_pnData[0] & 0x1F;
    146                                 if(nNalUnitType == 7)
    147                                         SpsBlobList.Add(&Blob);
    148                                 else
    149                                 if(nNalUnitType == 8)
    150                                         PpsBlobList.Add(&Blob);
    151                                 //else
    152                                 //      continue;
    153                         }
    154                         if(!SpsBlobList.IsEmpty() || !PpsBlobList.IsEmpty())
    155                         {
    156                                 // NOTE: See MPEG-4 Part 15, 5.2.4.1.1 Syntax
    157                                 AvcDecoderConfigurationRecordBlob.m_nDataSize = 64 << 10; // 64 KB
    158                                 __D(AvcDecoderConfigurationRecordBlob.m_pnData.Allocate(AvcDecoderConfigurationRecordBlob.m_nDataSize), E_OUTOFMEMORY);
    159                                 BYTE* A = AvcDecoderConfigurationRecordBlob.m_pnData;
    160                                 A[0] = 1; // configurationVersion
    161                                 A[1] = 100; // MPEG-4 Part 10, profile_idc, A.2.4 High profile
    162                                 A[2] = 0; // profile_compatibility
    163                                 A[3] = 40; // MPEG-4 Part 10, level_idc
    164                                 A[4] = 0xFC | 3; // lengthSizeMinusOne, 4 byte long lengths
    165                                 A += 5;
    166                                 BYTE* pnSequenceParameterSetCount = A++;
    167                                 *pnSequenceParameterSetCount = 0xE0 | SpsBlobList.GetCount();
    168                                 for(auto&& pSpsBlob: SpsBlobList)
    169                                 {
    170                                         *((NUINT16*) A) = (UINT16) pSpsBlob->m_nDataSize;
    171                                         A += sizeof (NUINT16);
    172                                         memcpy(A, pSpsBlob->m_pnData, pSpsBlob->m_nDataSize);
    173                                         A += pSpsBlob->m_nDataSize;
     189                                CRoListT<CBlob> BlobList;
     190                                CRoArrayT<CBlob*> SpsBlobList, PpsBlobList;
     191                                for(UINT nIndex = 0; ; nIndex++)
     192                                {
     193                                        // NOTE: Naming sample: MediaType_00
     194                                        const CString sName = AtlFormatString(_T("MediaType_%02d"), nIndex);
     195                                        CPath sPath = Combine(g_pszDirectory, sName);
     196                                        if(!sPath.FileExists())
     197                                                break;
     198                                        CBlob& Blob = BlobList.GetAt(BlobList.AddTail());
     199                                        _W(ReadFileData(sPath, Blob));
     200                                        _tprintf(_T("Read %d bytes from %s\n"), Blob.m_nDataSize, sName);
     201                                        if(Blob.m_nDataSize < 1)
     202                                                continue;
     203                                        const UINT nNalUnitType = Blob.m_pnData[0] & 0x1F;
     204                                        if(nNalUnitType == 7)
     205                                                SpsBlobList.Add(&Blob);
     206                                        else
     207                                        if(nNalUnitType == 8)
     208                                                PpsBlobList.Add(&Blob);
     209                                        //else
     210                                        //      continue;
    174211                                }
    175                                 BYTE* pnPictureParameterSetCount = A++;
    176                                 *pnPictureParameterSetCount = 0x00 | PpsBlobList.GetCount();
    177                                 for(auto&& pPpsBlob: PpsBlobList)
    178                                 {
    179                                         *((NUINT16*) A) = (UINT16) pPpsBlob->m_nDataSize;
    180                                         A += sizeof (NUINT16);
    181                                         memcpy(A, pPpsBlob->m_pnData, pPpsBlob->m_nDataSize);
    182                                         A += pPpsBlob->m_nDataSize;
     212                                if(!SpsBlobList.IsEmpty() || !PpsBlobList.IsEmpty())
     213                                {
     214                                        // NOTE: See MPEG-4 Part 15, 5.2.4.1.1 Syntax
     215                                        AvcDecoderConfigurationRecordBlob.m_nDataSize = 64 << 10; // 64 KB
     216                                        __D(AvcDecoderConfigurationRecordBlob.m_pnData.Allocate(AvcDecoderConfigurationRecordBlob.m_nDataSize), E_OUTOFMEMORY);
     217                                        BYTE* A = AvcDecoderConfigurationRecordBlob.m_pnData;
     218                                        A[0] = 1; // configurationVersion
     219                                        A[1] = 100; // MPEG-4 Part 10, profile_idc, A.2.4 High profile
     220                                        A[2] = 0; // profile_compatibility
     221                                        A[3] = 40; // MPEG-4 Part 10, level_idc
     222                                        A[4] = 0xFC | 3; // lengthSizeMinusOne, 4 byte long lengths
     223                                        A += 5;
     224                                        BYTE* pnSequenceParameterSetCount = A++;
     225                                        *pnSequenceParameterSetCount = 0xE0 | SpsBlobList.GetCount();
     226                                        for(auto&& pSpsBlob: SpsBlobList)
     227                                        {
     228                                                *((NUINT16*) A) = (UINT16) pSpsBlob->m_nDataSize;
     229                                                A += sizeof (NUINT16);
     230                                                memcpy(A, pSpsBlob->m_pnData, pSpsBlob->m_nDataSize);
     231                                                A += pSpsBlob->m_nDataSize;
     232                                        }
     233                                        BYTE* pnPictureParameterSetCount = A++;
     234                                        *pnPictureParameterSetCount = 0x00 | PpsBlobList.GetCount();
     235                                        for(auto&& pPpsBlob: PpsBlobList)
     236                                        {
     237                                                *((NUINT16*) A) = (UINT16) pPpsBlob->m_nDataSize;
     238                                                A += sizeof (NUINT16);
     239                                                memcpy(A, pPpsBlob->m_pnData, pPpsBlob->m_nDataSize);
     240                                                A += pPpsBlob->m_nDataSize;
     241                                        }
     242                                        _A((SIZE_T) (A - AvcDecoderConfigurationRecordBlob.m_pnData) <= AvcDecoderConfigurationRecordBlob.m_nDataSize);
     243                                        AvcDecoderConfigurationRecordBlob.m_nDataSize = A - AvcDecoderConfigurationRecordBlob.m_pnData;
     244                                        pAvCodecContext->extradata_size = (int) AvcDecoderConfigurationRecordBlob.m_nDataSize;
     245                                        pAvCodecContext->extradata = (BYTE*) AvcDecoderConfigurationRecordBlob.m_pnData;
    183246                                }
    184                                 _A((SIZE_T) (A - AvcDecoderConfigurationRecordBlob.m_pnData) <= AvcDecoderConfigurationRecordBlob.m_nDataSize);
    185                                 AvcDecoderConfigurationRecordBlob.m_nDataSize = A - AvcDecoderConfigurationRecordBlob.m_pnData;
    186                                 pAvCodecContext->extradata_size = (int) AvcDecoderConfigurationRecordBlob.m_nDataSize;
    187                                 pAvCodecContext->extradata = (BYTE*) AvcDecoderConfigurationRecordBlob.m_pnData;
    188247                        }
    189248                }
Note: See TracChangeset for help on using the changeset viewer.