source: trunk/Utilities/FFmpeg/DecodeMpeg4Video02/libav.h @ 937

Last change on this file since 937 was 591, checked in by roman, 6 years ago
File size: 16.0 KB
Line 
1////////////////////////////////////////////////////////////
2// Copyright (C) Roman Ryltsov, 2008-2015
3// Created by Roman Ryltsov roman@alax.info
4
5#pragma once
6
7#include <wmcodecdsp.h>
8#import "libid:B9EC374B-834B-4DA9-BFB5-C1872CE736FF" raw_interfaces_only // AlaxInfoDirectShowSpy
9#include "rodshow.h"
10#include "rodmo.h"
11
12#pragma comment(lib, "wmcodecdspuuid.lib")
13
14////////////////////////////////////////////////////////////
15// Libav (FFmpeg)
16
17#pragma warning(disable: 4244)
18
19#define __STDC_CONSTANT_MACROS
20
21extern "C" 
22{
23    #include <libavutil\avutil.h>
24    #include <libavutil\opt.h>
25    #include <libavcodec\avcodec.h>
26    //#include <libavcodec\avformat.h>
27    #include <libswscale\swscale.h>
28}
29
30#pragma warning(default: 4244)
31
32#pragma comment(lib, "avutil.lib")
33#pragma comment(lib, "avcodec.lib")
34//#pragma comment(lib, "avformat.lib")
35#pragma comment(lib, "swscale.lib")
36
37#define FACILITY_FFMPEG 'FF'
38
39#define FFMPEG_E_FAIL MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, __LINE__)
40
41////////////////////////////////////////////////////////////
42// Helper
43
44inline CString AvFormatResult(INT nErrorResult)
45{
46        CHAR pszDescription[256] = { 0 };
47        av_strerror(nErrorResult, pszDescription, _countof(pszDescription));
48        return CString(pszDescription);
49}
50
51#if _DEVELOPMENT
52        #define _Z3_AVRESULT(nResult) if(nResult < 0) { _Z3(atlTraceGeneral, 3, _T("FFmpeg failure, %s\n"), AvFormatResult(nResult)); }
53#else
54        #define _Z3_AVRESULT(nResult) (0)
55#endif // _DEVELOPMENT
56
57////////////////////////////////////////////////////////////
58// CAvLockManager
59
60class CAvLockManager
61{
62private:
63        static BOOL g_bRegistered;
64
65        static int LockOperation(void** ppvLock, enum AVLockOp Operation) 
66        {
67                _Z5(atlTraceGeneral, 5, _T("ppvLock 0x%p, Operation %d\n"), ppvLock, Operation);
68                _A(ppvLock);
69                CComCriticalSection* pCriticalSection = static_cast<CComCriticalSection*>(*ppvLock);
70                switch(Operation) 
71                {
72                case AV_LOCK_CREATE:
73                        {
74                                *ppvLock = new CComCriticalSection;
75                                if(!*ppvLock)
76                                        return 1; // Failure
77                                CComCriticalSection* pCriticalSection = static_cast<CComCriticalSection*>(*ppvLock);
78                                _V(pCriticalSection->Init());
79                        }
80                        return 0;
81                case AV_LOCK_OBTAIN:
82                        _V(pCriticalSection->Lock());
83                        return 0;
84                case AV_LOCK_RELEASE:
85                        _V(pCriticalSection->Unlock());
86                        return 0;
87                case AV_LOCK_DESTROY:
88                        _V(pCriticalSection->Term());
89                        delete pCriticalSection;
90                        *ppvLock = NULL;
91                        return 0;
92                }
93                return 1; // Failure
94        }
95
96public:
97// CAvLockManager
98        static VOID Register()
99        {
100                _A(_pAtlModule);
101                CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
102                if(g_bRegistered)
103                        return;
104                av_lockmgr_register(&CAvLockManager::LockOperation);
105                g_bRegistered = TRUE;
106        }
107        static BOOL IsRegistered()
108        {
109                _A(_pAtlModule);
110                CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
111                return g_bRegistered;
112        }
113};
114
115__declspec(selectany) BOOL CAvLockManager::g_bRegistered = FALSE;
116
117////////////////////////////////////////////////////////////
118// CAvAllocator, CAvHeapPtr
119
120class CAvAllocator
121{
122public:
123// CAvAllocator
124        static VOID* Allocate(_In_ SIZE_T nDataSize)
125        {
126                return av_malloc(nDataSize);
127        }
128        static VOID* Reallocate(_In_ VOID* pvData, _In_ SIZE_T nDataSize)
129        {
130                return av_realloc(pvData, nDataSize);
131        }
132        static VOID Free(_In_ VOID* pvData)
133        {
134                av_freep(pvData);
135        }
136};
137
138template <typename _Element>
139class CAvHeapPtr :
140        public CHeapPtr<_Element, CAvAllocator>
141{
142public:
143// CAvHeapPtr
144};
145
146////////////////////////////////////////////////////////////
147// CAvCodec
148
149class CAvCodec
150{
151private:
152        static BOOL g_bRegistered;
153
154        static VOID Log(VOID* ppvAvClass, int nLevel, const char* pszFormat, va_list Arguments)
155        {
156                #if _DEVELOPMENT //&& FALSE
157                        COMPILER_MESSAGE("Development: Enabled libavcodec logging")
158                        _ATLTRY
159                        {
160                                AVClass* pAvClass = ppvAvClass ? *((AVClass**) ppvAvClass) : NULL;
161                                CHAR pszText[32 << 10] = { 0 }; // 32 KB
162                                CStringA sFormat(pszFormat);
163                                sFormat.Replace("%td", "%d");
164                                vsprintf_s(pszText, sFormat, Arguments);
165                                CRoArrayT<CStringA> StringArray;
166                                _StringHelper::Split(pszText, '\n', StringArray);
167                                for(SIZE_T nIndex = 0; nIndex < StringArray.GetCount(); nIndex++)
168                                        //_Z2(atlTraceGeneral, 2, _T("%hs, nLevel %d, pAvClass 0x%p\n"), StringArray[nIndex], nLevel, pAvClass);
169                                        _Z2(atlTraceGeneral, 2, _T("%hs, nLevel %d\n"), StringArray[nIndex], nLevel);
170                                #if _DEVELOPMENT && FALSE
171                                        static LPCSTR g_pszPattern = " ooo";
172                                        if(strstr(pszText, g_pszPattern))
173                                                GetTickCount();
174                                                //AtlMessageBox(GetActiveWindow(), (LPCTSTR) AtlFormatString(_T("CAvCodec::Log: %hs"), pszText), _T("Debug"), MB_OK);
175                                #endif // _DEVELOPMENT
176                        }
177                        _ATLCATCHALL()
178                        {
179                                //_Z_EXCEPTION();
180                        }
181                #endif // _DEVELOPMENT
182        }
183
184public:
185// CAvCodec
186        static VOID Register(BOOL bSetLogCallback = FALSE)
187        {
188                bSetLogCallback;
189                _A(_pAtlModule);
190                CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
191                if(g_bRegistered)
192                        return;
193                _Z4(atlTraceGeneral, 4, _T("bSetLogCallback %d\n"), bSetLogCallback);
194                avcodec_register_all();
195                #if _DEVELOPMENT
196                        if(bSetLogCallback)
197                        {
198                                av_log_set_callback(&CAvCodec::Log);
199                                av_log_set_level(AV_LOG_DEBUG);
200                        }
201                #endif // _DEVELOPMENT
202                g_bRegistered = TRUE;
203        }
204        static BOOL IsRegistered()
205        {
206                _A(_pAtlModule);
207                CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
208                return g_bRegistered;
209        }
210        static AVCodec* FindEncoder(AVCodecID nCodec)
211        {
212                return avcodec_find_encoder(nCodec);
213        }
214        static AVCodec* FindDecoder(AVCodecID nCodec)
215        {
216                return avcodec_find_decoder(nCodec);
217        }
218};
219
220__declspec(selectany) BOOL CAvCodec::g_bRegistered = FALSE;
221
222////////////////////////////////////////////////////////////
223// CAvPointerT
224
225template <typename CType>
226class CAvPointerT
227{
228protected:
229        CType* m_p;
230
231public:
232// CAvPointerT
233        CAvPointerT() :
234                m_p(NULL)
235        {
236        }
237        ~CAvPointerT()
238        {
239                _A(!m_p);
240        }
241        CType* GetInstance() const
242        {
243                return m_p;
244        }
245        operator CType* () const
246        {
247                //_A(m_p);
248                return GetInstance();
249        }
250        CType* operator -> () const
251        {
252                _A(m_p);
253                return GetInstance();
254        }
255};
256
257////////////////////////////////////////////////////////////
258// CAvPacketT, CAvPacket
259
260template <BOOL t_bManaged>
261class CAvPacketT :
262        public AVPacket
263{
264public:
265// CAvPacketT
266        CAvPacketT()
267        {
268                if(t_bManaged)
269                {
270                        ZeroMemory(this, sizeof *this);
271                        av_init_packet(this);
272                }
273        }
274        explicit CAvPacketT(const BYTE* pnData, SIZE_T nDataSize)
275        {
276                ZeroMemory(this, sizeof *this);
277                if(t_bManaged)
278                        av_init_packet(this);
279                data = const_cast<uint8_t*>(pnData);
280                size = static_cast<int>(nDataSize);
281        }
282        ~CAvPacketT()
283        {
284                if(t_bManaged)
285                        av_packet_unref(this);
286        }
287};
288
289typedef CAvPacketT<TRUE> CAvPacket;
290
291////////////////////////////////////////////////////////////
292// CAvFrame
293
294class CAvFrame :
295        public CAvPointerT<AVFrame>
296{
297public:
298// CAvFrame
299        CAvFrame()
300        {
301        }
302        ~CAvFrame()
303        {
304                Free();
305        }
306        VOID Allocate()
307        {
308                _A(!m_p);
309                m_p = av_frame_alloc();
310                __D(m_p, FFMPEG_E_FAIL);
311        }
312        VOID Free()
313        {
314                if(!m_p)
315                        return;
316                av_free(m_p);
317                m_p = NULL;
318        }
319};
320
321////////////////////////////////////////////////////////////
322// CAvCodecContext
323
324class CAvCodecContext :
325        public CAvPointerT<AVCodecContext>
326{
327public:
328// CAvCodecContext
329        CAvCodecContext()
330        {
331        }
332        ~CAvCodecContext()
333        {
334                Free();
335        }
336        VOID Allocate(AVCodec* pAvCodec)
337        {
338                _A(pAvCodec);
339                _A(!m_p);
340                _A(CAvCodec::IsRegistered());
341                m_p = avcodec_alloc_context3(pAvCodec);
342                __D(m_p, FFMPEG_E_FAIL);
343        }
344        VOID Free()
345        {
346                if(!m_p)
347                        return;
348                av_free(m_p);
349                m_p = NULL;
350        }
351        VOID Open(AVCodec* pAvCodec)
352        {
353                _A(pAvCodec);
354                _A(m_p);
355                __D(avcodec_open2(m_p, pAvCodec, NULL) >= 0, FFMPEG_E_FAIL);
356        }
357        VOID Close()
358        {
359                _A(m_p);
360                _W(avcodec_close(m_p) >= 0);
361        }
362        BOOL EncodeVideo(AVPacket* pAvPacket, const AVFrame* pAvFrame)
363        {
364                _A(m_p);
365                INT nPacketAvailable = 0;
366                const INT nResult = avcodec_encode_video2(m_p, pAvPacket, pAvFrame, &nPacketAvailable);
367                _Z3_AVRESULT(nResult);
368                __D(nResult >= 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
369                return nPacketAvailable != 0;
370        }
371        BOOL EncodeVideo(AVPacket* pAvPacket, const CAvFrame& pAvFrame)
372        {
373                return EncodeVideo(pAvPacket, (const AVFrame*) pAvFrame);
374        }
375        BOOL DecodeVideo(CAvFrame& pAvFrame, const AVPacket* pAvPacket, SIZE_T& nProcessedDataSize)
376        {
377                _A(m_p);
378                INT nFrameAvailable = 0;
379                const INT nResult = avcodec_decode_video2(m_p, pAvFrame, &nFrameAvailable, pAvPacket);
380                _Z3_AVRESULT(nResult);
381                __D(nResult >= 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
382                nProcessedDataSize = (SIZE_T) nResult;
383                return nFrameAvailable != 0;
384        }
385        BOOL EncodeAudio(AVPacket* pAvPacket, const AVFrame* pAvFrame)
386        {
387                _A(m_p);
388                INT nPacketAvailable = 0;
389                const INT nResult = avcodec_encode_audio2(m_p, pAvPacket, pAvFrame, &nPacketAvailable);
390                _Z3_AVRESULT(nResult);
391                __D(nResult >= 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
392                return nPacketAvailable != 0;
393        }
394        BOOL EncodeAudio(AVPacket* pAvPacket, const CAvFrame& pAvFrame)
395        {
396                return EncodeAudio(pAvPacket, (const AVFrame*) pAvFrame);
397        }
398        BOOL DecodeAudio(CAvFrame& pAvFrame, const AVPacket* pAvPacket, SIZE_T& nProcessedDataSize)
399        {
400                _A(m_p);
401                INT nFrameAvailable = 0;
402                const INT nResult = avcodec_decode_audio4(m_p, pAvFrame, &nFrameAvailable, pAvPacket);
403                _Z3_AVRESULT(nResult);
404                __D(nResult >= 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
405                nProcessedDataSize = (SIZE_T) nResult;
406                return nFrameAvailable != 0;
407        }
408        BOOL DecodeAudio(CAvFrame& pAvFrame)
409        {
410                _A(m_p);
411                INT nFrameAvailable = 0;
412                const INT nResult = avcodec_decode_audio4(m_p, pAvFrame, &nFrameAvailable, NULL);
413                _Z3_AVRESULT(nResult);
414                __D(nResult >= 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
415                return nFrameAvailable != 0;
416        }
417};
418
419////////////////////////////////////////////////////////////
420// CAvIoContext
421
422//class CAvIoContext
423//{
424//private:
425//      AVIOContext* m_p;
426//
427//public:
428//// CAvIoContext
429//      CAvIoContext() :
430//              m_p(NULL)
431//      {
432//      }
433//      ~CAvIoContext()
434//      {
435//              Terminate();
436//      }
437//      VOID Initialize(const CHAR* pszPath, INT nFlags) // AVIO_FLAG_
438//      {
439//              _A(!m_p);
440//              const INT nResult = avio_open(&m_p, pszPath, nFlags);
441//              __D(nResult == 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
442//              _A(m_p);
443//      }
444//      VOID Initialize(const WCHAR* pszPath, INT nFlags)
445//      {
446//              Initialize(CW2A(pszPath), nFlags);
447//      }
448//      VOID Terminate()
449//      {
450//              if(!m_p)
451//                      return;
452//              avio_close(m_p);
453//              m_p = NULL;
454//      }
455//      operator AVIOContext* ()
456//      {
457//              return m_p;
458//      }
459//      AVIOContext* operator -> ()
460//      {
461//              _A(m_p);
462//              return m_p;
463//      }
464//};
465
466////////////////////////////////////////////////////////////
467// CAvFormatContext
468
469//class CAvFormatContext
470//{
471//private:
472//      AVFormatContext* m_p;
473//
474//public:
475//// CAvFormatContext
476//      CAvFormatContext() :
477//              m_p(NULL)
478//      {
479//      }
480//      ~CAvFormatContext()
481//      {
482//              Terminate();
483//      }
484//      VOID Initialize(AVOutputFormat* pOutputFormat, const CHAR* pszFormatName, const CHAR* pszFileName = NULL)
485//      {
486//              _A(!m_p);
487//              const INT nResult = avformat_alloc_output_context2(&m_p, pOutputFormat, pszFormatName, pszFileName);
488//              __D(nResult >= 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
489//              _A(m_p);
490//      }
491//      VOID Initialize(const CHAR* pszFormatName, const CHAR* pszFileName = NULL)
492//      {
493//              _A(pszFormatName);
494//              Initialize(NULL, pszFormatName, pszFileName);
495//      }
496//      VOID Terminate()
497//      {
498//              if(!m_p)
499//                      return;
500//              _A(!m_p->nb_streams);
501//              avformat_free_context(m_p);
502//              m_p = NULL;
503//      }
504//      operator AVFormatContext* ()
505//      {
506//              return m_p;
507//      }
508//      AVFormatContext* operator -> ()
509//      {
510//              _A(m_p);
511//              return m_p;
512//      }
513//      CAvIoContext& GetIoContext()
514//      {
515//              _A(m_p);
516//              return reinterpret_cast<CAvIoContext&>(m_p->pb);
517//      }
518//      AVStream* NewStream(AVCodec* pCodec)
519//      {
520//              _A(m_p);
521//              AVStream* pAvStream = avformat_new_stream(m_p, pCodec);
522//              __D(pAvStream, FFMPEG_E_FAIL);
523//              return pAvStream;
524//      }
525//      VOID FreeStreams()
526//      {
527//              _A(m_p);
528//              for(UINT nStreamIndex = 0; nStreamIndex < m_p->nb_streams; nStreamIndex++)
529//              {
530//                      CAvAllocator::Free(&m_p->streams[nStreamIndex]->codec);
531//                      CAvAllocator::Free(&m_p->streams[nStreamIndex]);
532//              }
533//              m_p->nb_streams = 0;
534//      }
535//      VOID WriteHeader(AVDictionary** ppOptions = NULL)
536//      {
537//              _A(m_p);
538//              const INT nResult = avformat_write_header(m_p, ppOptions);
539//              __D(nResult == 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
540//      }
541//      VOID WriteFrame(AVPacket* pPacket)
542//      {
543//              _A(pPacket);
544//              _A(m_p);
545//              const INT nResult = av_interleaved_write_frame(m_p, pPacket);
546//              __D(nResult == 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
547//      }
548//      VOID WriteTrailer()
549//      {
550//              _A(m_p);
551//              const INT nResult = av_write_trailer(m_p);
552//              __D(nResult == 0, MAKE_HRESULT(SEVERITY_ERROR, FACILITY_FFMPEG, (WORD) nResult));
553//      }
554//};
555
556////////////////////////////////////////////////////////////
557// CAvAll
558
559//class CAvAll
560//{
561//private:
562//      static BOOL g_bRegistered;
563//
564//      static VOID Log(VOID* ppvAvClass, int nLevel, const char* pszFormat, va_list Arguments)
565//      {
566//              #if _DEVELOPMENT
567//                      _ATLTRY
568//                      {
569//                              AVClass* pAvClass = ppvAvClass ? *((AVClass**) ppvAvClass) : NULL;
570//                              CHAR pszText[32 << 10] = { 0 }; // 32 KB
571//                              vsprintf_s(pszText, pszFormat, Arguments);
572//                              CRoArrayT<CStringA> StringArray;
573//                              _StringHelper::Split(pszText, '\n', StringArray);
574//                              for(SIZE_T nIndex = 0; nIndex < StringArray.GetCount(); nIndex++)
575//                                      _Z2(atlTraceGeneral, 2, _T("%hs, nLevel %d, pAvClass 0x%p\n"), StringArray[nIndex], nLevel, pAvClass);
576//                              #if _DEVELOPMENT && FALSE
577//                                      static LPCSTR g_pszPattern = "decode_slice_header";
578//                                      if(strstr(pszText, g_pszPattern))
579//                                              AtlMessageBox(GetActiveWindow(), (LPCTSTR) AtlFormatString(_T("CAvAll::Log: %hs"), pszText), _T("Debug"), MB_OK);
580//                              #endif // _DEVELOPMENT
581//                      }
582//                      _ATLCATCHALL()
583//                      {
584//                              //_Z_EXCEPTION();
585//                      }
586//              #endif // _DEVELOPMENT
587//      }
588//
589//public:
590//// CAvAll
591//      static VOID Register(BOOL bSetLogCallback = FALSE)
592//      {
593//              bSetLogCallback;
594//              _A(_pAtlModule);
595//              CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
596//              if(g_bRegistered)
597//                      return;
598//              av_register_all();
599//              #if _DEVELOPMENT
600//                      if(bSetLogCallback)
601//                      {
602//                              av_log_set_callback(&CAvAll::Log);
603//                              av_log_set_level(AV_LOG_DEBUG);
604//                      }
605//              #endif // _DEVELOPMENT
606//              g_bRegistered = TRUE;
607//      }
608//      static BOOL IsRegistered()
609//      {
610//              _A(_pAtlModule);
611//              CComCritSecLock<CComCriticalSection> Lock(_pAtlModule->m_csStaticDataInitAndTypeInfo);
612//              return g_bRegistered;
613//      }
614//};
615//
616//__declspec(selectany) BOOL CAvAll::g_bRegistered = FALSE;
617
618////////////////////////////////////////////////////////////
619// CSwsContext
620
621class CSwsContext :
622        public CAvPointerT<SwsContext>
623{
624public:
625// CSwsContext
626        CSwsContext()
627        {
628        }
629        ~CSwsContext()
630        {
631                Free();
632        }
633        VOID Get(SIZE SourceExtent, AVPixelFormat SourcePixelFormat, SIZE DestinationExtent, AVPixelFormat DestinationPixelFormat, UINT nFlags = SWS_FAST_BILINEAR, SwsFilter* pSourceFilter = NULL, SwsFilter* pDestinationFilter = NULL)
634        {
635                _A(!m_p);
636                m_p = sws_getContext(SourceExtent.cx, SourceExtent.cy, SourcePixelFormat, DestinationExtent.cx, DestinationExtent.cy, DestinationPixelFormat, nFlags, pSourceFilter, pDestinationFilter, NULL);
637                __D(m_p, E_OUTOFMEMORY);
638        }
639        VOID Free()
640        {
641                if(!m_p)
642                        return;
643                sws_freeContext(m_p);
644                m_p = NULL;
645        }
646        VOID Scale(const BYTE* const ppnSourcePlanes[], const INT pnSourceStrides[], INT nSliceIndex, INT nSliceCount, BYTE* const ppnDestinationPlanes[], const INT pnDestinationStrides[])
647        {
648                _A(m_p);
649                sws_scale(m_p, ppnSourcePlanes, pnSourceStrides, nSliceIndex, nSliceCount, ppnDestinationPlanes, pnDestinationStrides);
650        }
651};
652
Note: See TracBrowser for help on using the repository browser.