diff --git a/src/AudioOutputDSound.cpp b/src/AudioOutputDSound.cpp new file mode 100644 index 00000000..aa845f4c --- /dev/null +++ b/src/AudioOutputDSound.cpp @@ -0,0 +1,418 @@ +/****************************************************************************** + AudioOutputDSound.cpp: description + Copyright (C) 2012-2014 Wang Bin + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +******************************************************************************/ + + +#include "QtAV/AudioOutput.h" +#include "QtAV/private/AudioOutput_p.h" +#include "prepost.h" +#include +#include + +#include +#define DIRECTSOUND_VERSION 0x0600 +#include +#include "QtAV/private/AVCompat.h" + +namespace QtAV { +class AudioOutputDSoundPrivate; +class AudioOutputDSound : public AudioOutput +{ + DPTR_DECLARE_PRIVATE(AudioOutputDSound) +public: + AudioOutputDSound(); + ~AudioOutputDSound(); + //AudioOutputId id() const + virtual bool open(); + virtual bool close(); + virtual bool isSupported(const AudioFormat& format) const; + virtual void waitForNextBuffer(); +protected: + virtual bool write(); +}; + +extern AudioOutputId AudioOutputId_DSound; +FACTORY_REGISTER_ID_AUTO(AudioOutput, DSound, "DirectSound") + +void RegisterAudioOutputDSound_Man() +{ + FACTORY_REGISTER_ID_MAN(AudioOutput, DSound, "DirectSound") +} + + +template void SafeRelease(T **ppT) { + if (*ppT) { + (*ppT)->Release(); + *ppT = NULL; + } +} + +// use the definitions from the win32 api headers when they define these +#define WAVE_FORMAT_IEEE_FLOAT 0x0003 +#define WAVE_FORMAT_DOLBY_AC3_SPDIF 0x0092 +#define WAVE_FORMAT_EXTENSIBLE 0xFFFE +/* GUID SubFormat IDs */ +/* We need both b/c const variables are not compile-time constants in C, giving + * us an error if we use the const GUID in an enum */ + +#ifndef _KSDATAFORMAT_SUBTYPE_PCM_ +#define _KSDATAFORMAT_SUBTYPE_PCM_ {0x00000001, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} +static const GUID VLC_KSDATAFORMAT_SUBTYPE_PCM = {0xE923AABF, 0xCB58, 0x4471, {0xA1, 0x19, 0xFF, 0xFA, 0x01, 0xE4, 0xCE, 0x62}}; +#define KSDATAFORMAT_SUBTYPE_PCM VLC_KSDATAFORMAT_SUBTYPE_PCM +#endif + +#ifndef _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_ +#define _KSDATAFORMAT_SUBTYPE_IEEE_FLOAT_ {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}} +static const GUID VLC_KSDATAFORMAT_SUBTYPE_IEEE_FLOAT = {0x00000003, 0x0000, 0x0010, {0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}}; +#define KSDATAFORMAT_SUBTYPE_IEEE_FLOAT VLC_KSDATAFORMAT_SUBTYPE_PCM +#endif + +#ifndef _KSDATAFORMAT_SUBTYPE_UNKNOWN_ +#define _KSDATAFORMAT_SUBTYPE_UNKNOWN_ {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}} +static const GUID VLC_KSDATAFORMAT_SUBTYPE_UNKNOWN = {0x00000000, 0x0000, 0x0000, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}; +#define KSDATAFORMAT_SUBTYPE_UNKNOWN VLC_KSDATAFORMAT_SUBTYPE_UNKNOWN +#endif + +#ifndef _WAVEFORMATEXTENSIBLE_ +typedef struct { + WAVEFORMATEX Format; + union { + WORD wValidBitsPerSample; /* bits of precision */ + WORD wSamplesPerBlock; /* valid if wBitsPerSample==0 */ + WORD wReserved; /* If neither applies, set to zero. */ + } Samples; + DWORD dwChannelMask; /* which channels are */ + /* present in stream */ + GUID SubFormat; +} WAVEFORMATEXTENSIBLE, *PWAVEFORMATEXTENSIBLE; +#endif + +/* Microsoft speaker definitions. key/values are equal to FFmpeg's */ +#define SPEAKER_FRONT_LEFT 0x1 +#define SPEAKER_FRONT_RIGHT 0x2 +#define SPEAKER_FRONT_CENTER 0x4 +#define SPEAKER_LOW_FREQUENCY 0x8 +#define SPEAKER_BACK_LEFT 0x10 +#define SPEAKER_BACK_RIGHT 0x20 +#define SPEAKER_FRONT_LEFT_OF_CENTER 0x40 +#define SPEAKER_FRONT_RIGHT_OF_CENTER 0x80 +#define SPEAKER_BACK_CENTER 0x100 +#define SPEAKER_SIDE_LEFT 0x200 +#define SPEAKER_SIDE_RIGHT 0x400 +#define SPEAKER_TOP_CENTER 0x800 +#define SPEAKER_TOP_FRONT_LEFT 0x1000 +#define SPEAKER_TOP_FRONT_CENTER 0x2000 +#define SPEAKER_TOP_FRONT_RIGHT 0x4000 +#define SPEAKER_TOP_BACK_LEFT 0x8000 +#define SPEAKER_TOP_BACK_CENTER 0x10000 +#define SPEAKER_TOP_BACK_RIGHT 0x20000 +#define SPEAKER_RESERVED 0x80000000 + +static int channelMaskToMS(qint64 av) { + if (av >= (qint64)SPEAKER_RESERVED) + return 0; + return (int)av; +} + +static int channelLayoutToMS(qint64 av) { + return channelMaskToMS(av); +} + +static const char* dserr2str(int err) { + switch (err) { + case DS_OK: return "DS_OK"; + case DS_NO_VIRTUALIZATION: return "DS_NO_VIRTUALIZATION"; + case DSERR_ALLOCATED: return "DS_NO_VIRTUALIZATION"; + case DSERR_CONTROLUNAVAIL: return "DSERR_CONTROLUNAVAIL"; + case DSERR_INVALIDPARAM: return "DSERR_INVALIDPARAM"; + case DSERR_INVALIDCALL: return "DSERR_INVALIDCALL"; + case DSERR_GENERIC: return "DSERR_GENERIC"; + case DSERR_PRIOLEVELNEEDED: return "DSERR_PRIOLEVELNEEDED"; + case DSERR_OUTOFMEMORY: return "DSERR_OUTOFMEMORY"; + case DSERR_BADFORMAT: return "DSERR_BADFORMAT"; + case DSERR_UNSUPPORTED: return "DSERR_UNSUPPORTED"; + case DSERR_NODRIVER: return "DSERR_NODRIVER"; + case DSERR_ALREADYINITIALIZED: return "DSERR_ALREADYINITIALIZED"; + case DSERR_NOAGGREGATION: return "DSERR_NOAGGREGATION"; + case DSERR_BUFFERLOST: return "DSERR_BUFFERLOST"; + case DSERR_OTHERAPPHASPRIO: return "DSERR_OTHERAPPHASPRIO"; + case DSERR_UNINITIALIZED: return "DSERR_UNINITIALIZED"; + case DSERR_NOINTERFACE: return "DSERR_NOINTERFACE"; + case DSERR_ACCESSDENIED: return "DSERR_ACCESSDENIED"; + default: return "unknown"; + } +} + +class AudioOutputDSoundPrivate : public AudioOutputPrivate +{ +public: + AudioOutputDSoundPrivate() + : AudioOutputPrivate() + , dll(NULL) + , prim_buf(NULL) + , stream_buf(NULL) + , write_offset(0) + { + } + ~AudioOutputDSoundPrivate() { + } + bool loadDll(); + bool unloadDll(); + bool init(); + void destroy() { + SafeRelease(&dsound); + SafeRelease(&prim_buf); + SafeRelease(&stream_buf); + unloadDll(); + } + bool createDSoundBuffers(); + + HINSTANCE dll; + LPDIRECTSOUND dsound; ///direct sound object + LPDIRECTSOUNDBUFFER prim_buf; ///primary direct sound buffer + LPDIRECTSOUNDBUFFER stream_buf; ///secondary direct sound buffer (stream buffer) + int write_offset; ///offset of the write cursor in the direct sound buffer +}; + +AudioOutputDSound::AudioOutputDSound() + :AudioOutput(*new AudioOutputDSoundPrivate()) +{ +} + +AudioOutputDSound::~AudioOutputDSound() +{ + close(); +} + +bool AudioOutputDSound::open() +{ + DPTR_D(AudioOutputDSound); + if (!d.init()) + return false; + if (!d.createDSoundBuffers()) + return false; + return true; +} + +bool AudioOutputDSound::close() +{ + DPTR_D(AudioOutputDSound); + d.destroy(); + return true; +} + +bool AudioOutputDSound::isSupported(const AudioFormat &format) const +{ + Q_UNUSED(format); + return true; +} + +void AudioOutputDSound::waitForNextBuffer() +{ + DPTR_D(AudioOutputDSound); + if (!d.dsound) + return; + DWORD read_offset; + d.stream_buf->GetCurrentPosition(&read_offset /*play*/, NULL /*write*/); + int remain = d.write_offset - read_offset; + if (remain < 0LL) { + remain += d.bufferSizeTotal(); + } + if (remain > 0) { + // don't need AudioOutputPrivate buffer queue + unsigned long duration = d.format.durationForBytes((qint64)remain)/1000LL; + QMutexLocker lock(&d.mutex); + Q_UNUSED(lock); + d.cond.wait(&d.mutex, duration); + } + d.bufferRemoved(); //TODO: virtual void noWait(); +} + +bool AudioOutputDSound::write() //TODO: deprecated, use write(AudioFrame or QByteArray) +{ + DPTR_D(AudioOutputDSound); + LPVOID dst1, dst2; + DWORD size1, size2; + if (d.write_offset > d.bufferSizeTotal()) + d.write_offset = 0; + HRESULT res = d.stream_buf->Lock(d.write_offset, d.data.size(), &dst1, &size1, &dst2, &size2, 0); + if (res == DSERR_BUFFERLOST) { + d.stream_buf->Restore(); + res = d.stream_buf->Lock(d.write_offset, d.data.size(), &dst1, &size1, &dst2, &size2, 0); + } + if (res != DS_OK) { + qWarning("Can not lock secondary buffer (%s)", dserr2str(res)); + return false; + } + memcpy(dst1, d.data.constData(), size1); + if (dst2) + memcpy(dst2, d.data.constData() + size1, size2); + d.write_offset += size1 + size2; + if (d.write_offset > d.bufferSizeTotal()) + d.write_offset = size2; + res = d.stream_buf->Unlock(dst1, size1, dst2, size2); + if (res != DS_OK) { + qWarning("Unloack error (%s)",dserr2str(res)); + //return false; + } + DWORD status; + d.stream_buf->GetStatus(&status); + if (!(status & DSBSTATUS_PLAYING)) { + d.stream_buf->Play(0, 0, DSBPLAY_LOOPING); + } + return true; +} + +bool AudioOutputDSoundPrivate::loadDll() +{ + dll = LoadLibrary(TEXT("dsound.dll")); + if (!dll) { + qWarning("Can not load dsound.dll"); + return false; + } + return true; +} + +bool AudioOutputDSoundPrivate::unloadDll() +{ + if (dll) + FreeLibrary(dll); + return true; +} + +bool AudioOutputDSoundPrivate::init() +{ + if (!loadDll()) + return false; + typedef HRESULT (WINAPI *DirectSoundCreateFunc)(LPGUID, LPDIRECTSOUND *, LPUNKNOWN); + //typedef HRESULT (WINAPI *DirectSoundEnumerateFunc)(LPDSENUMCALLBACKA, LPVOID); + DirectSoundCreateFunc dsound_create = (DirectSoundCreateFunc)GetProcAddress(dll, "DirectSoundCreate"); + //DirectSoundEnumerateFunc dsound_enumerate = (DirectSoundEnumerateFunc)GetProcAddress(dll, "DirectSoundEnumerateA"); + if (!dsound_create) { + qWarning("Failed to resolve 'DirectSoundCreate'"); + unloadDll(); + return false; + } + if (FAILED(dsound_create(NULL/*dev guid*/, &dsound, NULL))){ + unloadDll(); + return false; + } + /* DSSCL_EXCLUSIVE: can modify the settings of the primary buffer, only the sound of this app will be hearable when it will have the focus. + */ + if (FAILED(dsound->SetCooperativeLevel(GetDesktopWindow(), DSSCL_EXCLUSIVE))) { + qWarning("Cannot set direct sound cooperative level"); + SafeRelease(&dsound); + return false; + } + qDebug("DirectSound initialized."); + DSCAPS dscaps; + memset(&dscaps, 0, sizeof(DSCAPS)); + dscaps.dwSize = sizeof(DSCAPS); + if (FAILED(dsound->GetCaps(&dscaps))) { + qWarning("Cannot get device capabilities."); + SafeRelease(&dsound); + return false; + } + if (dscaps.dwFlags & DSCAPS_EMULDRIVER) + qDebug("DirectSound is emulated"); + + write_offset = 0; + return true; +} + +/** + * Creates a DirectSound buffer of the required format. + * + * This function creates the buffer we'll use to play audio. + * In DirectSound there are two kinds of buffers: + * - the primary buffer: which is the actual buffer that the soundcard plays + * - the secondary buffer(s): these buffers are the one actually used by + * applications and DirectSound takes care of mixing them into the primary. + * + * Once you create a secondary buffer, you cannot change its format anymore so + * you have to release the current one and create another. + */ +bool AudioOutputDSoundPrivate::createDSoundBuffers() +{ + WAVEFORMATEXTENSIBLE wformat; + // TODO: Dolby Digital AC3 + ZeroMemory(&wformat, sizeof(WAVEFORMATEXTENSIBLE)); + wformat.Format.cbSize = 0; + wformat.Format.nChannels = format.channels(); + wformat.Format.nSamplesPerSec = format.sampleRate(); + wformat.Format.wFormatTag = WAVE_FORMAT_PCM; + wformat.Format.wBitsPerSample = format.bytesPerSample() * 8; + wformat.Format.nBlockAlign = wformat.Format.nChannels * format.bytesPerSample(); + wformat.Format.nAvgBytesPerSec = wformat.Format.nSamplesPerSec * wformat.Format.nBlockAlign; + wformat.dwChannelMask = channelLayoutToMS(format.channelLayoutFFmpeg()); + if (format.channels() > 2) { + wformat.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + wformat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + wformat.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + wformat.Samples.wValidBitsPerSample = wformat.Format.wBitsPerSample; + } + // fill in primary sound buffer descriptor + DSBUFFERDESC dsbpridesc; + memset(&dsbpridesc, 0, sizeof(DSBUFFERDESC)); + dsbpridesc.dwSize = sizeof(DSBUFFERDESC); + dsbpridesc.dwFlags = DSBCAPS_PRIMARYBUFFER; + dsbpridesc.dwBufferBytes = 0; + dsbpridesc.lpwfxFormat = NULL; + // create primary buffer and set its format + HRESULT res = dsound->CreateSoundBuffer(&dsbpridesc, &prim_buf, NULL); + if (res != DS_OK) { + destroy(); + qWarning("Cannot create primary buffer (%s)", dserr2str(res)); + return false; + } + res = prim_buf->SetFormat((WAVEFORMATEX *)&wformat); + if (res != DS_OK) { + qWarning("Cannot set primary buffer format (%s), using standard setting (bad quality)", dserr2str(res)); + } + qDebug("primary buffer created"); + + // fill in the secondary sound buffer (=stream buffer) descriptor + DSBUFFERDESC dsbdesc; + memset(&dsbdesc, 0, sizeof(DSBUFFERDESC)); + dsbdesc.dwSize = sizeof(DSBUFFERDESC); + dsbdesc.dwFlags = DSBCAPS_GETCURRENTPOSITION2 /** Better position accuracy */ + | DSBCAPS_GLOBALFOCUS /** Allows background playing */ + | DSBCAPS_CTRLVOLUME; /** volume control enabled */ + dsbdesc.dwBufferBytes = bufferSizeTotal(); + dsbdesc.lpwfxFormat = (WAVEFORMATEX *)&wformat; + // Needed for 5.1 on emu101k - shit soundblaster + if (format.channels() > 2) + dsbdesc.dwFlags |= DSBCAPS_LOCHARDWARE; + // now create the stream buffer + res = dsound->CreateSoundBuffer(&dsbdesc, &stream_buf, NULL); + if (res != DS_OK) { + if (dsbdesc.dwFlags & DSBCAPS_LOCHARDWARE) { + // Try without DSBCAPS_LOCHARDWARE + dsbdesc.dwFlags &= ~DSBCAPS_LOCHARDWARE; + res = dsound->CreateSoundBuffer(&dsbdesc, &stream_buf, NULL); + } + if (res != DS_OK) { + destroy(); + qWarning("Cannot create secondary (stream)buffer (%s)", dserr2str(res)); + return false; + } + } + qDebug( "Secondary (stream)buffer created"); + return true; +} + +} // namespace QtAV diff --git a/src/AudioOutputOpenAL.cpp b/src/AudioOutputOpenAL.cpp index b64faf40..d4a46175 100644 --- a/src/AudioOutputOpenAL.cpp +++ b/src/AudioOutputOpenAL.cpp @@ -166,9 +166,6 @@ static ALenum audioFormatToAL(const AudioFormat& fmt) return format; } -const int kBufferSize = 1024*4; -const int kBufferCount = 8; - class AudioOutputOpenALPrivate : public AudioOutputPrivate { public: diff --git a/src/AudioOutputTypes.cpp b/src/AudioOutputTypes.cpp index abdcf20c..2c0ba339 100644 --- a/src/AudioOutputTypes.cpp +++ b/src/AudioOutputTypes.cpp @@ -28,6 +28,7 @@ namespace QtAV { AudioOutputId AudioOutputId_PortAudio = 1; AudioOutputId AudioOutputId_OpenAL = 2; AudioOutputId AudioOutputId_OpenSL = 3; +AudioOutputId AudioOutputId_DSound = 4; QVector GetRegistedAudioOutputIds() { @@ -40,6 +41,7 @@ FACTORY_DEFINE(AudioOutput) extern void RegisterAudioOutputPortAudio_Man(); extern void RegisterAudioOutputOpenAL_Man(); extern void RegisterAudioOutputOpenSL_Man(); +extern void RegisterAudioOutputDSound_Man(); void AudioOutput_RegisterAll() { @@ -52,6 +54,9 @@ void AudioOutput_RegisterAll() #if QTAV_HAVE(OPENSL) RegisterAudioOutputOpenSL_Man(); #endif //QTAV_HAVE(OPENSL) +#if QTAV_HAVE(DSOUND) + extern void RegisterAudioOutputDSound_Man(); +#endif } } //namespace QtAV diff --git a/src/QtAV/AudioOutputTypes.h b/src/QtAV/AudioOutputTypes.h index 584a2d9a..13445d65 100644 --- a/src/QtAV/AudioOutputTypes.h +++ b/src/QtAV/AudioOutputTypes.h @@ -37,6 +37,7 @@ Q_AV_EXPORT QVector GetRegistedAudioOutputIds(); extern Q_AV_EXPORT AudioOutputId AudioOutputId_PortAudio; extern Q_AV_EXPORT AudioOutputId AudioOutputId_OpenAL; extern Q_AV_EXPORT AudioOutputId AudioOutputId_OpenSL; +extern Q_AV_EXPORT AudioOutputId AudioOutputId_DSound; Q_AV_EXPORT void AudioOutput_RegisterAll(); diff --git a/src/QtAV/private/AudioOutput_p.h b/src/QtAV/private/AudioOutput_p.h index e23f17a1..746f3c42 100644 --- a/src/QtAV/private/AudioOutput_p.h +++ b/src/QtAV/private/AudioOutput_p.h @@ -29,8 +29,13 @@ #include #include +// TODO:writeChunk(), write(QByteArray) { while writeChunk() }, users define writeChunk() namespace QtAV { +// chunk +const int kBufferSize = 1024*4; +const int kBufferCount = 8; + class Q_AV_PRIVATE_EXPORT AudioOutputPrivate : public AVOutputPrivate { public: @@ -48,6 +53,7 @@ public: } virtual ~AudioOutputPrivate(){} + int bufferSizeTotal() { return nb_buffers * kBufferCount; } typedef struct { qreal timestamp; int data_size; diff --git a/src/libQtAV.pro b/src/libQtAV.pro index 9f1aed66..f4cfac51 100644 --- a/src/libQtAV.pro +++ b/src/libQtAV.pro @@ -1,340 +1,346 @@ -TEMPLATE = lib -TARGET = QtAV -QT += core gui -greaterThan(QT_MAJOR_VERSION, 4) { - QT += widgets -} -CONFIG *= qtav-buildlib -INCLUDEPATH += $$[QT_INSTALL_HEADERS] - -#var with '_' can not pass to pri? -STATICLINK = 0 -PROJECTROOT = $$PWD/.. -!include(libQtAV.pri): error("could not find libQtAV.pri") -preparePaths($$OUT_PWD/../out) - -RESOURCES += ../i18n/QtAV.qrc \ - shaders/shaders.qrc - -win32 { - RC_FILE = $${PROJECTROOT}/res/QtAV.rc -#no depends for rc file by default, even if rc includes a header. Makefile target use '/' as default, so not works iwth win cmd - rc.target = $$clean_path($$RC_FILE) #rc obj depends on clean path target - rc.depends = $$PWD/QtAV/version.h -#why use multiple rule failed? i.e. add a rule without command - isEmpty(QMAKE_SH) { - rc.commands = @copy /B $$system_path($$RC_FILE)+,, #change file time - } else { - rc.commands = @touch $$RC_FILE #change file time - } - QMAKE_EXTRA_TARGETS += rc -} -# copy runtime libs to qt sdk -!ios: copy_sdk_libs = $$DESTDIR/$$qtSharedLib($$NAME) -#plugin.depends = #makefile target -#windows: copy /y file1+file2+... dir. need '+' -for(f, copy_sdk_libs) { - win32: copy_sdk_libs_cmd += $$quote(-\$\(COPY_FILE\) \"$$system_path($$f)\" \"$$system_path($$[QT_INSTALL_BINS])\") - else: copy_sdk_libs_cmd += $$quote(-\$\(COPY_FILE\) \"$$system_path($$f)\" \"$$system_path($$[QT_INSTALL_LIBS])\") -} -#join values seperated by space. so quote is needed -copy_sdk_libs_cmd = $$join(copy_sdk_libs_cmd,$$escape_expand(\\n\\t)) -#just append as a string to $$QMAKE_POST_LINK -isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK = $$copy_sdk_libs_cmd -else: QMAKE_POST_LINK = $${QMAKE_POST_LINK}$$escape_expand(\\n\\t)$$copy_sdk_libs_cmd - -OTHER_FILES += $$RC_FILE -TRANSLATIONS = $${PROJECTROOT}/i18n/QtAV_zh_CN.ts - -## sse2 sse4_1 may be defined in Qt5 qmodule.pri but is not included. Qt4 defines sse and sse2 -sse4_1|config_sse4_1|contains(TARGET_ARCH_SUB, sse4.1) { - CONFIG += sse2 #only sse4.1 is checked. sse2 now can be disabled if sse4.1 is disabled - DEFINES += QTAV_HAVE_SSE4_1=1 -## TODO: use SSE4_1_SOURCES -# all x64 processers supports sse2. unknown option for vc - *msvc* { - !isEqual(QT_ARCH, x86_64)|!x86_64: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE4_1 - } else { - QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE4_1 #gcc -msse4.1 - } -} -sse2|config_sse2|contains(TARGET_ARCH_SUB, sse2) { - DEFINES += QTAV_HAVE_SSE2=1 -# all x64 processers supports sse2. unknown option for vc - *msvc* { - !isEqual(QT_ARCH, x86_64)|!x86_64: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2 - } else { - QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2 #gcc -msse2 - } -} - -*msvc* { -#link FFmpeg and portaudio which are built by gcc need /SAFESEH:NO - QMAKE_LFLAGS += /SAFESEH:NO - INCLUDEPATH += compat/msvc -} -#UINT64_C: C99 math features, need -D__STDC_CONSTANT_MACROS in CXXFLAGS -DEFINES += __STDC_CONSTANT_MACROS -android: CONFIG += config_opensl -android: LIBS += -lavcodec-55 -lavformat-55 -lavutil-52 -lswscale-2 -else: LIBS += -lavcodec -lavformat -lavutil -lswscale -config_avfilter { - DEFINES += QTAV_HAVE_AVFILTER=1 - SOURCES += LibAVFilter.cpp - HEADERS += QtAV/LibAVFilter.h - android: LIBS += -lavfilter-4 - else: LIBS += -lavfilter -} -config_swresample { - DEFINES += QTAV_HAVE_SWRESAMPLE=1 - SOURCES += AudioResamplerFF.cpp - android: LIBS += -lswresample-0 - else: LIBS += -lswresample -} -config_avresample { - DEFINES += QTAV_HAVE_AVRESAMPLE=1 - SOURCES += AudioResamplerLibav.cpp - android: LIBS += -lavresample-1 - else: LIBS += -lavresample -} -config_ipp { - DEFINES += QTAV_HAVE_IPP=1 - ICCROOT = $$(IPPROOT)/../compiler - INCLUDEPATH += $$(IPPROOT)/include - SOURCES += ImageConverterIPP.cpp - message("QMAKE_TARGET.arch" $$QMAKE_TARGET.arch) - *64|contains(QMAKE_TARGET.arch, x86_64)|contains(TARGET_ARCH, x86_64) { - IPPARCH=intel64 - } else { - IPPARCH=ia32 - } - LIBS *= -L$$(IPPROOT)/lib/$$IPPARCH -lippcc -lippcore -lippi \ - -L$$(IPPROOT)/../compiler/lib/$$IPPARCH -lsvml -limf - #omp for static link. _t is multi-thread static link -} -config_portaudio { - SOURCES += AudioOutputPortAudio.cpp - DEFINES *= QTAV_HAVE_PORTAUDIO=1 - LIBS *= -lportaudio - #win32: LIBS *= -lwinmm #-lksguid #-luuid -} -config_openal { - SOURCES += AudioOutputOpenAL.cpp - DEFINES *= QTAV_HAVE_OPENAL=1 - win32: LIBS += -lOpenAL32 - unix:!mac:!blackberry: LIBS += -lopenal - blackberry: LIBS += -lOpenAL - mac: LIBS += -framework OpenAL - mac: DEFINES += HEADER_OPENAL_PREFIX -} -config_opensl { - SOURCES += AudioOutputOpenSL.cpp - DEFINES *= QTAV_HAVE_OPENSL=1 - LIBS += -lOpenSLES -} -config_gdiplus { - DEFINES *= QTAV_HAVE_GDIPLUS=1 - SOURCES += GDIRenderer.cpp - SDK_HEADERS += QtAV/GDIRenderer.h - LIBS += -lgdiplus -lGdi32 -} -config_direct2d { - DEFINES *= QTAV_HAVE_DIRECT2D=1 - !*msvc*: INCLUDEPATH += $$PROJECTROOT/contrib/d2d1headers - SOURCES += Direct2DRenderer.cpp - SDK_HEADERS += QtAV/Direct2DRenderer.h - #LIBS += -lD2d1 -} -config_xv { - DEFINES *= QTAV_HAVE_XV=1 - SOURCES += XVRenderer.cpp - SDK_HEADERS += QtAV/XVRenderer.h - LIBS += -lXv -} -config_gl { - QT *= opengl - DEFINES *= QTAV_HAVE_GL=1 - SOURCES += GLWidgetRenderer.cpp GLWidgetRenderer2.cpp - SDK_HEADERS += QtAV/GLWidgetRenderer.h QtAV/GLWidgetRenderer2.h - OTHER_FILES += shaders/planar.f.glsl shaders/rgb.f.glsl -} -CONFIG += config_cuda #config_dllapi config_dllapi_cuda -#CONFIG += config_cuda_link -config_cuda { - DEFINES += QTAV_HAVE_CUDA=1 - HEADERS += cuda/dllapi/nv_inc.h cuda/helper_cuda.h - SOURCES += VideoDecoderCUDA.cpp - INCLUDEPATH += $$PWD/cuda cuda/dllapi - config_dllapi:config_dllapi_cuda { - DEFINES += QTAV_HAVE_DLLAPI_CUDA=1 - INCLUDEPATH += ../depends/dllapi/src -include(../depends/dllapi/src/libdllapi.pri) - SOURCES += cuda/dllapi/cuda.cpp cuda/dllapi/nvcuvid.cpp cuda/dllapi/cuviddec.cpp - } else:config_cuda_link { - DEFINES += CUDA_LINK - INCLUDEPATH += $$(CUDA_PATH)/include - LIBS += -L$$(CUDA_PATH)/lib - isEqual(TARGET_ARCH, x86): LIBS += -L$$(CUDA_PATH)/lib/Win32 - else: LIBS += -L$$(CUDA_PATH)/lib/x64 - LIBS += -lnvcuvid -lcuda - } - SOURCES += cuda/cuda_api.cpp - HEADERS += cuda/cuda_api.h -} -config_dxva { - DEFINES *= QTAV_HAVE_DXVA=1 - SOURCES += VideoDecoderDXVA.cpp - LIBS += -lOle32 -} -config_vaapi* { - DEFINES *= QTAV_HAVE_VAAPI=1 - SOURCES += VideoDecoderVAAPI.cpp - LIBS += -lva #dynamic load va-glx va-x11 using dllapi -} -config_libcedarv { - DEFINES *= QTAV_HAVE_CEDARV=1 - SOURCES += VideoDecoderCedarv.cpp - LIBS += -lvecore -lcedarv -} -macx:!ios: CONFIG += config_vda -config_vda { - DEFINES *= QTAV_HAVE_VDA=1 - SOURCES += VideoDecoderVDA.cpp - LIBS += -framework VideoDecodeAcceleration -framework CoreVideo -} -SOURCES += \ - AVCompat.cpp \ - QtAV_Global.cpp \ - utils/GPUMemCopy.cpp \ - utils/OpenGLHelper.cpp \ - QAVIOContext.cpp \ - ShaderManager.cpp \ - AudioThread.cpp \ - AVThread.cpp \ - AudioDecoder.cpp \ - AudioFormat.cpp \ - AudioFrame.cpp \ - AudioOutput.cpp \ - AudioOutputTypes.cpp \ - AudioResampler.cpp \ - AudioResamplerTypes.cpp \ - AVDecoder.cpp \ - AVDemuxer.cpp \ - AVDemuxThread.cpp \ - ColorTransform.cpp \ - Frame.cpp \ - Filter.cpp \ - FilterContext.cpp \ - FilterManager.cpp \ - GraphicsItemRenderer.cpp \ - ImageConverter.cpp \ - ImageConverterFF.cpp \ - QPainterRenderer.cpp \ - OSD.cpp \ - OSDFilter.cpp \ - Packet.cpp \ - AVError.cpp \ - AVPlayer.cpp \ - AVClock.cpp \ - VideoCapture.cpp \ - VideoFormat.cpp \ - VideoFrame.cpp \ - VideoRenderer.cpp \ - VideoRendererTypes.cpp \ - VideoOutput.cpp \ - VideoOutputEventFilter.cpp \ - WidgetRenderer.cpp \ - AVOutput.cpp \ - OutputSet.cpp \ - OpenGLVideo.cpp \ - VideoShader.cpp \ - Statistics.cpp \ - VideoDecoder.cpp \ - VideoDecoderTypes.cpp \ - VideoDecoderFFmpeg.cpp \ - VideoDecoderFFmpegHW.cpp \ - VideoThread.cpp \ - CommonTypes.cpp - -SDK_HEADERS *= \ - QtAV/QtAV.h \ - QtAV/dptr.h \ - QtAV/QtAV_Global.h \ - QtAV/AudioResampler.h \ - QtAV/AudioResamplerTypes.h \ - QtAV/AudioDecoder.h \ - QtAV/AudioFormat.h \ - QtAV/AudioFrame.h \ - QtAV/AudioOutput.h \ - QtAV/AudioOutputTypes.h \ - QtAV/AVDecoder.h \ - QtAV/AVDemuxer.h \ - QtAV/CommonTypes.h \ - QtAV/Filter.h \ - QtAV/FilterContext.h \ - QtAV/Frame.h \ - QtAV/GraphicsItemRenderer.h \ - QtAV/ImageConverter.h \ - QtAV/ImageConverterTypes.h \ - QtAV/QPainterRenderer.h \ - QtAV/OSD.h \ - QtAV/OSDFilter.h \ - QtAV/OpenGLVideo.h \ - QtAV/VideoShader.h \ - QtAV/Packet.h \ - QtAV/AVError.h \ - QtAV/AVPlayer.h \ - QtAV/VideoCapture.h \ - QtAV/VideoRenderer.h \ - QtAV/VideoRendererTypes.h \ - QtAV/VideoOutput.h \ - QtAV/WidgetRenderer.h \ - QtAV/AVOutput.h \ - QtAV/AVClock.h \ - QtAV/VideoDecoder.h \ - QtAV/VideoDecoderTypes.h \ - QtAV/VideoFormat.h \ - QtAV/VideoFrame.h \ - QtAV/FactoryDefine.h \ - QtAV/Statistics.h \ - QtAV/SurfaceInterop.h \ - QtAV/version.h - -# QtAV/private/* may be used by developers to extend QtAV features without changing QtAV library -# headers not in QtAV/ and it's subdirs are used only by QtAV internally -HEADERS *= \ - $$SDK_HEADERS \ - utils/BlockingQueue.h \ - utils/GPUMemCopy.h \ - utils/OpenGLHelper.h \ - QtAV/prepost.h \ - QtAV/AVDemuxThread.h \ - QtAV/AVThread.h \ - QtAV/AudioThread.h \ - QtAV/VideoThread.h \ - QtAV/ColorTransform.h \ - QtAV/VideoDecoderFFmpegHW.h \ - QtAV/private/factory.h \ - QtAV/private/singleton.h \ - QtAV/private/AVCompat.h \ - QtAV/private/AudioOutput_p.h \ - QtAV/private/AudioResampler_p.h \ - QtAV/private/AVThread_p.h \ - QtAV/private/AVDecoder_p.h \ - QtAV/private/AVOutput_p.h \ - QtAV/private/Filter_p.h \ - QtAV/private/FilterManager.h \ - QtAV/private/Frame_p.h \ - QtAV/private/ImageConverter_p.h \ - QtAV/private/OutputSet.h \ - QtAV/private/QAVIOContext.h \ - QtAV/private/ShaderManager.h \ - QtAV/private/VideoShader_p.h \ - QtAV/private/VideoDecoder_p.h \ - QtAV/private/VideoDecoderFFmpegHW_p.h \ - QtAV/private/VideoOutputEventFilter.h \ - QtAV/private/VideoRenderer_p.h \ - QtAV/private/QPainterRenderer_p.h - -SDK_INCLUDE_FOLDER = QtAV -include($$PROJECTROOT/deploy.pri) +TEMPLATE = lib +TARGET = QtAV +QT += core gui +greaterThan(QT_MAJOR_VERSION, 4) { + QT += widgets +} +CONFIG *= qtav-buildlib +INCLUDEPATH += $$[QT_INSTALL_HEADERS] + +#var with '_' can not pass to pri? +STATICLINK = 0 +PROJECTROOT = $$PWD/.. +!include(libQtAV.pri): error("could not find libQtAV.pri") +preparePaths($$OUT_PWD/../out) + +RESOURCES += ../i18n/QtAV.qrc \ + shaders/shaders.qrc + +win32 { + RC_FILE = $${PROJECTROOT}/res/QtAV.rc +#no depends for rc file by default, even if rc includes a header. Makefile target use '/' as default, so not works iwth win cmd + rc.target = $$clean_path($$RC_FILE) #rc obj depends on clean path target + rc.depends = $$PWD/QtAV/version.h +#why use multiple rule failed? i.e. add a rule without command + isEmpty(QMAKE_SH) { + rc.commands = @copy /B $$system_path($$RC_FILE)+,, #change file time + } else { + rc.commands = @touch $$RC_FILE #change file time + } + QMAKE_EXTRA_TARGETS += rc +} +# copy runtime libs to qt sdk +!ios: copy_sdk_libs = $$DESTDIR/$$qtSharedLib($$NAME) +#plugin.depends = #makefile target +#windows: copy /y file1+file2+... dir. need '+' +for(f, copy_sdk_libs) { + win32: copy_sdk_libs_cmd += $$quote(-\$\(COPY_FILE\) \"$$system_path($$f)\" \"$$system_path($$[QT_INSTALL_BINS])\") + else: copy_sdk_libs_cmd += $$quote(-\$\(COPY_FILE\) \"$$system_path($$f)\" \"$$system_path($$[QT_INSTALL_LIBS])\") +} +#join values seperated by space. so quote is needed +copy_sdk_libs_cmd = $$join(copy_sdk_libs_cmd,$$escape_expand(\\n\\t)) +#just append as a string to $$QMAKE_POST_LINK +isEmpty(QMAKE_POST_LINK): QMAKE_POST_LINK = $$copy_sdk_libs_cmd +else: QMAKE_POST_LINK = $${QMAKE_POST_LINK}$$escape_expand(\\n\\t)$$copy_sdk_libs_cmd + +OTHER_FILES += $$RC_FILE +TRANSLATIONS = $${PROJECTROOT}/i18n/QtAV_zh_CN.ts + +## sse2 sse4_1 may be defined in Qt5 qmodule.pri but is not included. Qt4 defines sse and sse2 +sse4_1|config_sse4_1|contains(TARGET_ARCH_SUB, sse4.1) { + CONFIG += sse2 #only sse4.1 is checked. sse2 now can be disabled if sse4.1 is disabled + DEFINES += QTAV_HAVE_SSE4_1=1 +## TODO: use SSE4_1_SOURCES +# all x64 processers supports sse2. unknown option for vc + *msvc* { + !isEqual(QT_ARCH, x86_64)|!x86_64: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE4_1 + } else { + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE4_1 #gcc -msse4.1 + } +} +sse2|config_sse2|contains(TARGET_ARCH_SUB, sse2) { + DEFINES += QTAV_HAVE_SSE2=1 +# all x64 processers supports sse2. unknown option for vc + *msvc* { + !isEqual(QT_ARCH, x86_64)|!x86_64: QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2 + } else { + QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_SSE2 #gcc -msse2 + } +} + +win32: CONFIG += config_dsound + +*msvc* { +#link FFmpeg and portaudio which are built by gcc need /SAFESEH:NO + #QMAKE_LFLAGS += /SAFESEH:NO + INCLUDEPATH += compat/msvc +} +#UINT64_C: C99 math features, need -D__STDC_CONSTANT_MACROS in CXXFLAGS +DEFINES += __STDC_CONSTANT_MACROS +android: CONFIG += config_opensl +android: LIBS += -lavcodec-55 -lavformat-55 -lavutil-52 -lswscale-2 +else: LIBS += -lavcodec -lavformat -lavutil -lswscale +config_avfilter { + DEFINES += QTAV_HAVE_AVFILTER=1 + SOURCES += LibAVFilter.cpp + HEADERS += QtAV/LibAVFilter.h + android: LIBS += -lavfilter-4 + else: LIBS += -lavfilter +} +config_swresample { + DEFINES += QTAV_HAVE_SWRESAMPLE=1 + SOURCES += AudioResamplerFF.cpp + android: LIBS += -lswresample-0 + else: LIBS += -lswresample +} +config_avresample { + DEFINES += QTAV_HAVE_AVRESAMPLE=1 + SOURCES += AudioResamplerLibav.cpp + android: LIBS += -lavresample-1 + else: LIBS += -lavresample +} +config_ipp { + DEFINES += QTAV_HAVE_IPP=1 + ICCROOT = $$(IPPROOT)/../compiler + INCLUDEPATH += $$(IPPROOT)/include + SOURCES += ImageConverterIPP.cpp + message("QMAKE_TARGET.arch" $$QMAKE_TARGET.arch) + *64|contains(QMAKE_TARGET.arch, x86_64)|contains(TARGET_ARCH, x86_64) { + IPPARCH=intel64 + } else { + IPPARCH=ia32 + } + LIBS *= -L$$(IPPROOT)/lib/$$IPPARCH -lippcc -lippcore -lippi \ + -L$$(IPPROOT)/../compiler/lib/$$IPPARCH -lsvml -limf + #omp for static link. _t is multi-thread static link +} +config_dsound { + SOURCES += AudioOutputDSound.cpp + DEFINES *= QTAV_HAVE_DSOUND=1 +} +config_portaudio { + SOURCES += AudioOutputPortAudio.cpp + DEFINES *= QTAV_HAVE_PORTAUDIO=1 + LIBS *= -lportaudio + #win32: LIBS *= -lwinmm #-lksguid #-luuid +} +config_openal { + SOURCES += AudioOutputOpenAL.cpp + DEFINES *= QTAV_HAVE_OPENAL=1 + win32: LIBS += -lOpenAL32 + unix:!mac:!blackberry: LIBS += -lopenal + blackberry: LIBS += -lOpenAL + mac: LIBS += -framework OpenAL + mac: DEFINES += HEADER_OPENAL_PREFIX +} +config_opensl { + SOURCES += AudioOutputOpenSL.cpp + DEFINES *= QTAV_HAVE_OPENSL=1 + LIBS += -lOpenSLES +} +config_gdiplus { + DEFINES *= QTAV_HAVE_GDIPLUS=1 + SOURCES += GDIRenderer.cpp + SDK_HEADERS += QtAV/GDIRenderer.h + LIBS += -lgdiplus -lgdi32 +} +config_direct2d { + DEFINES *= QTAV_HAVE_DIRECT2D=1 + !*msvc*: INCLUDEPATH += $$PROJECTROOT/contrib/d2d1headers + SOURCES += Direct2DRenderer.cpp + SDK_HEADERS += QtAV/Direct2DRenderer.h + #LIBS += -lD2d1 +} +config_xv { + DEFINES *= QTAV_HAVE_XV=1 + SOURCES += XVRenderer.cpp + SDK_HEADERS += QtAV/XVRenderer.h + LIBS += -lXv +} +config_gl { + QT *= opengl + DEFINES *= QTAV_HAVE_GL=1 + SOURCES += GLWidgetRenderer.cpp GLWidgetRenderer2.cpp + SDK_HEADERS += QtAV/GLWidgetRenderer.h QtAV/GLWidgetRenderer2.h + OTHER_FILES += shaders/planar.f.glsl shaders/rgb.f.glsl +} +CONFIG += config_cuda #config_dllapi config_dllapi_cuda +#CONFIG += config_cuda_link +config_cuda { + DEFINES += QTAV_HAVE_CUDA=1 + HEADERS += cuda/dllapi/nv_inc.h cuda/helper_cuda.h + SOURCES += VideoDecoderCUDA.cpp + INCLUDEPATH += $$PWD/cuda cuda/dllapi + config_dllapi:config_dllapi_cuda { + DEFINES += QTAV_HAVE_DLLAPI_CUDA=1 + INCLUDEPATH += ../depends/dllapi/src +include(../depends/dllapi/src/libdllapi.pri) + SOURCES += cuda/dllapi/cuda.cpp cuda/dllapi/nvcuvid.cpp cuda/dllapi/cuviddec.cpp + } else:config_cuda_link { + DEFINES += CUDA_LINK + INCLUDEPATH += $$(CUDA_PATH)/include + LIBS += -L$$(CUDA_PATH)/lib + isEqual(TARGET_ARCH, x86): LIBS += -L$$(CUDA_PATH)/lib/Win32 + else: LIBS += -L$$(CUDA_PATH)/lib/x64 + LIBS += -lnvcuvid -lcuda + } + SOURCES += cuda/cuda_api.cpp + HEADERS += cuda/cuda_api.h +} +config_dxva { + DEFINES *= QTAV_HAVE_DXVA=1 + SOURCES += VideoDecoderDXVA.cpp + LIBS += -lole32 +} +config_vaapi* { + DEFINES *= QTAV_HAVE_VAAPI=1 + SOURCES += VideoDecoderVAAPI.cpp + LIBS += -lva #dynamic load va-glx va-x11 using dllapi +} +config_libcedarv { + DEFINES *= QTAV_HAVE_CEDARV=1 + SOURCES += VideoDecoderCedarv.cpp + LIBS += -lvecore -lcedarv +} +macx:!ios: CONFIG += config_vda +config_vda { + DEFINES *= QTAV_HAVE_VDA=1 + SOURCES += VideoDecoderVDA.cpp + LIBS += -framework VideoDecodeAcceleration -framework CoreVideo +} +SOURCES += \ + AVCompat.cpp \ + QtAV_Global.cpp \ + utils/GPUMemCopy.cpp \ + utils/OpenGLHelper.cpp \ + QAVIOContext.cpp \ + ShaderManager.cpp \ + AudioThread.cpp \ + AVThread.cpp \ + AudioDecoder.cpp \ + AudioFormat.cpp \ + AudioFrame.cpp \ + AudioOutput.cpp \ + AudioOutputTypes.cpp \ + AudioResampler.cpp \ + AudioResamplerTypes.cpp \ + AVDecoder.cpp \ + AVDemuxer.cpp \ + AVDemuxThread.cpp \ + ColorTransform.cpp \ + Frame.cpp \ + Filter.cpp \ + FilterContext.cpp \ + FilterManager.cpp \ + GraphicsItemRenderer.cpp \ + ImageConverter.cpp \ + ImageConverterFF.cpp \ + QPainterRenderer.cpp \ + OSD.cpp \ + OSDFilter.cpp \ + Packet.cpp \ + AVError.cpp \ + AVPlayer.cpp \ + AVClock.cpp \ + VideoCapture.cpp \ + VideoFormat.cpp \ + VideoFrame.cpp \ + VideoRenderer.cpp \ + VideoRendererTypes.cpp \ + VideoOutput.cpp \ + VideoOutputEventFilter.cpp \ + WidgetRenderer.cpp \ + AVOutput.cpp \ + OutputSet.cpp \ + OpenGLVideo.cpp \ + VideoShader.cpp \ + Statistics.cpp \ + VideoDecoder.cpp \ + VideoDecoderTypes.cpp \ + VideoDecoderFFmpeg.cpp \ + VideoDecoderFFmpegHW.cpp \ + VideoThread.cpp \ + CommonTypes.cpp + +SDK_HEADERS *= \ + QtAV/QtAV.h \ + QtAV/dptr.h \ + QtAV/QtAV_Global.h \ + QtAV/AudioResampler.h \ + QtAV/AudioResamplerTypes.h \ + QtAV/AudioDecoder.h \ + QtAV/AudioFormat.h \ + QtAV/AudioFrame.h \ + QtAV/AudioOutput.h \ + QtAV/AudioOutputTypes.h \ + QtAV/AVDecoder.h \ + QtAV/AVDemuxer.h \ + QtAV/CommonTypes.h \ + QtAV/Filter.h \ + QtAV/FilterContext.h \ + QtAV/Frame.h \ + QtAV/GraphicsItemRenderer.h \ + QtAV/ImageConverter.h \ + QtAV/ImageConverterTypes.h \ + QtAV/QPainterRenderer.h \ + QtAV/OSD.h \ + QtAV/OSDFilter.h \ + QtAV/OpenGLVideo.h \ + QtAV/VideoShader.h \ + QtAV/Packet.h \ + QtAV/AVError.h \ + QtAV/AVPlayer.h \ + QtAV/VideoCapture.h \ + QtAV/VideoRenderer.h \ + QtAV/VideoRendererTypes.h \ + QtAV/VideoOutput.h \ + QtAV/WidgetRenderer.h \ + QtAV/AVOutput.h \ + QtAV/AVClock.h \ + QtAV/VideoDecoder.h \ + QtAV/VideoDecoderTypes.h \ + QtAV/VideoFormat.h \ + QtAV/VideoFrame.h \ + QtAV/FactoryDefine.h \ + QtAV/Statistics.h \ + QtAV/SurfaceInterop.h \ + QtAV/version.h + +# QtAV/private/* may be used by developers to extend QtAV features without changing QtAV library +# headers not in QtAV/ and it's subdirs are used only by QtAV internally +HEADERS *= \ + $$SDK_HEADERS \ + utils/BlockingQueue.h \ + utils/GPUMemCopy.h \ + utils/OpenGLHelper.h \ + QtAV/prepost.h \ + QtAV/AVDemuxThread.h \ + QtAV/AVThread.h \ + QtAV/AudioThread.h \ + QtAV/VideoThread.h \ + QtAV/ColorTransform.h \ + QtAV/VideoDecoderFFmpegHW.h \ + QtAV/private/factory.h \ + QtAV/private/singleton.h \ + QtAV/private/AVCompat.h \ + QtAV/private/AudioOutput_p.h \ + QtAV/private/AudioResampler_p.h \ + QtAV/private/AVThread_p.h \ + QtAV/private/AVDecoder_p.h \ + QtAV/private/AVOutput_p.h \ + QtAV/private/Filter_p.h \ + QtAV/private/FilterManager.h \ + QtAV/private/Frame_p.h \ + QtAV/private/ImageConverter_p.h \ + QtAV/private/OutputSet.h \ + QtAV/private/QAVIOContext.h \ + QtAV/private/ShaderManager.h \ + QtAV/private/VideoShader_p.h \ + QtAV/private/VideoDecoder_p.h \ + QtAV/private/VideoDecoderFFmpegHW_p.h \ + QtAV/private/VideoOutputEventFilter.h \ + QtAV/private/VideoRenderer_p.h \ + QtAV/private/QPainterRenderer_p.h + +SDK_INCLUDE_FOLDER = QtAV +include($$PROJECTROOT/deploy.pri)