diff --git a/src/codec/video/VideoDecoderOMX.cpp b/src/codec/video/VideoDecoderOMX.cpp new file mode 100644 index 00000000..245b4779 --- /dev/null +++ b/src/codec/video/VideoDecoderOMX.cpp @@ -0,0 +1,131 @@ +/****************************************************************************** + QtAV: Multimedia framework based on Qt and FFmpeg + Copyright (C) 2012-2016 Wang Bin + +* This file is part of QtAV (from 2016) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +******************************************************************************/ + +#include "QtAV/VideoDecoder.h" +#include "QtAV/Packet.h" +#include "QtAV/private/AVDecoder_p.h" +#include "QtAV/private/factory.h" +#include +#include "QtAV/private/AVCompat.h" +#include "utils/BlockingQueue.h" +#include "openmax/OMXHelper.h" +#include "utils/Logger.h" + +namespace QtAV { + +class VideoDecoderOMXPrivate; +class VideoDecoderOMX : public VideoDecoder +{ + DPTR_DECLARE_PRIVATE(VideoDecoderOMX) +public: + VideoDecoderOMX(); + bool decode(const Packet& packet) Q_DECL_OVERRIDE; + VideoFrame frame() Q_DECL_OVERRIDE; + +}; + +struct omx_buf { + OMX_BUFFERHEADERTYPE *header; + QByteArray data; +}; + +class VideoDecoderOMXPrivate : public VideoDecoderPrivate, protected omx::core +{ +public: + static OMX_ERRORTYPE DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData); + static OMX_ERRORTYPE DecoderEmptyBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBuffer); + static OMX_ERRORTYPE DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE* pBufferHeader); + + bool open() Q_DECL_OVERRIDE; + void close() Q_DECL_OVERRIDE; + + OMX_HANDLETYPE dec; + QHash in_buffers; + BlockingQueue in_buffers_free; + BlockingQueue out_buffers; +}; + +OMX_ERRORTYPE VideoDecoderOMXPrivate::DecoderEventHandler(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_EVENTTYPE eEvent, OMX_U32 nData1, OMX_U32 nData2, OMX_PTR pEventData) +{ + + return OMX_ErrorNone; +} + +OMX_ERRORTYPE VideoDecoderOMXPrivate::DecoderEmptyBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE *pBuffer) +{ + Q_UNUSED(hComponent); + VideoDecoderOMXPrivate *p = static_cast(pAppData); + p->in_buffers_free.put(p->in_buffers[pBuffer]); + return OMX_ErrorNone; +} + +OMX_ERRORTYPE VideoDecoderOMXPrivate::DecoderFillBufferDone(OMX_HANDLETYPE hComponent, OMX_PTR pAppData, OMX_BUFFERHEADERTYPE *pBufferHeader) +{ + return OMX_ErrorNone; +} + +bool VideoDecoderOMXPrivate::open() +{ + + OMX_ENSURE(OMX_Init(), false); + static OMX_CALLBACKTYPE cb = { + DecoderEventHandler, + DecoderEmptyBufferDone, + DecoderFillBufferDone + }; + OMX_ENSURE(OMX_GetHandle(&dec, "...", this, &cb), false); + return true; +} + +void VideoDecoderOMXPrivate::close() +{ + OMX_WARN(OMX_Deinit()); +} + +bool VideoDecoderOMX::decode(const Packet &packet) +{ + DPTR_D(VideoDecoderOMX); + omx_buf buf = d.in_buffers_free.take(); + buf.data = packet.data; + OMX_BUFFERHEADERTYPE* h = buf.header; + h->nFlags = packet.isEOF() ? OMX_BUFFERFLAG_EOS : 0; + h->nOffset = 0; + h->pBuffer = (OMX_U8*)buf.data.constData(); + h->nAllocLen = buf.data.size(); + h->nFilledLen = buf.data.size(); + h->nTimeStamp = packet.pts*1000.0*1000.0; //us + h->pAppPrivate = &d; + //h->nInputPortIndex = ; + OMX_ENSURE(OMX_EmptyThisBuffer(d.dec, h), false); + return true; +} + +VideoFrame VideoDecoderOMX::frame() +{ + DPTR_D(VideoDecoderOMX); + if (d.out_buffers.isEmpty()) + return VideoFrame(); + OMX_BUFFERHEADERTYPE* h = d.out_buffers.take(); + OMX_ENSURE(OMX_FillThisBuffer(d.dec, h), VideoFrame()); + VideoFrame f; + return f; +} +} //namespace QtAV diff --git a/src/libQtAV.pro b/src/libQtAV.pro index 0498ed9d..a2c035d1 100644 --- a/src/libQtAV.pro +++ b/src/libQtAV.pro @@ -20,6 +20,8 @@ INCLUDEPATH += $$[QT_INSTALL_HEADERS] icon.files = $$PWD/$${TARGET}.svg icon.path = /usr/share/icons/hicolor/64x64/apps !contains(QMAKE_HOST.os, Windows):INSTALLS += icon +#UINT64_C: C99 math features, need -D__STDC_CONSTANT_MACROS in CXXFLAGS +DEFINES += __STDC_CONSTANT_MACROS #mac: simd.prf will load qt_build_config and the result is soname will prefixed with QT_INSTALL_LIBS and link flag will append soname after QMAKE_LFLAGS_SONAME config_libcedarv: CONFIG *= neon config_simd #need by qt4 addSimdCompiler(). neon or config_neon is required because tests/arch can not detect neon @@ -112,8 +114,11 @@ enable_egl:greaterThan(QT_MAJOR_VERSION,4):qtHaveModule(x11extras): QT *= x11ext config_gl|config_opengl { contains(QT_CONFIG, opengl):!contains(QT_CONFIG, opengles2): CONFIG *= enable_desktopgl } -#UINT64_C: C99 math features, need -D__STDC_CONSTANT_MACROS in CXXFLAGS -DEFINES += __STDC_CONSTANT_MACROS +config_openmax { + INCLUDEPATH += openmax/include + HEADERS += openmax/OMXHelper.h + SOURCES += openmax/OMXHelper.cpp codec/video/VideoDecoderOMX.cpp +} android { CONFIG *= config_opensl !no_gui_private:qtHaveModule(androidextras) { #qt5.2 has QAndroidJniObject diff --git a/src/openmax/OMXHelper.cpp b/src/openmax/OMXHelper.cpp new file mode 100644 index 00000000..c51bf5c5 --- /dev/null +++ b/src/openmax/OMXHelper.cpp @@ -0,0 +1,118 @@ +/****************************************************************************** + QtAV: Multimedia framework based on Qt and FFmpeg + Copyright (C) 2012-2016 Wang Bin + +* This file is part of QtAV (from 2016) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +******************************************************************************/ + +#include "OMXHelper.h" +#include +namespace QtAV { +namespace omx { + +static QLibrary sLib; + +typedef OMX_ERRORTYPE OMX_APIENTRY t_Init(); +typedef OMX_ERRORTYPE OMX_APIENTRY t_Deinit(); +typedef OMX_ERRORTYPE OMX_APIENTRY t_ComponentNameEnum( + OMX_OUT OMX_STRING cComponentName, + OMX_IN OMX_U32 nNameLength, + OMX_IN OMX_U32 nIndex); +typedef OMX_ERRORTYPE OMX_APIENTRY t_GetHandle( + OMX_OUT OMX_HANDLETYPE* pHandle, + OMX_IN OMX_STRING cComponentName, + OMX_IN OMX_PTR pAppData, + OMX_IN OMX_CALLBACKTYPE* pCallBacks); +typedef OMX_ERRORTYPE OMX_APIENTRY t_FreeHandle( + OMX_IN OMX_HANDLETYPE hComponent); +static t_Init *p_Init = 0; +static t_Deinit *p_Deinit = 0; +static t_ComponentNameEnum *p_ComponentNameEnum = 0; +static t_GetHandle *p_GetHandle = 0; +static t_FreeHandle *p_FreeHandle = 0; +static const char *kOMXLib[] = +{ + "libiomx.so", /* Not used when using IOMX, the lib should already be loaded */ + "/opt/vc/lib/libopenmaxil.so", /* Broadcom IL core */ + "libOMX_Core.so", /* TI OMAP IL core */ + "libOmxCore.so", /* Qualcomm IL core */ + "libnvomx.so", /* Tegra3 IL core */ + "libomxil-bellagio.so", /* Bellagio IL core reference implementation */ + "libSEC_OMX_Core.so", //SAMSUNG + 0 +}; + +core::core() +{ + if (sLib.isLoaded()) + return; + //load "/opt/vc/lib/libbcm_host.so" and call bcm_host_init first? + for (int i = 0; kOMXLib[i]; ++i) { + sLib.setFileName(QString::fromUtf8(kOMXLib[i])); + if (sLib.load()) + break; + } + if (!sLib.isLoaded()) + return; + struct { + void** pf; + const char* names[8]; + } sym_table[] = { + {(void**)&p_Init, {"OMX_Init", "SEC_OMX_Init", 0}}, + {(void**)&p_Deinit, {"OMX_Deinit", "SEC_OMX_Deinit", 0}}, + {(void**)&p_ComponentNameEnum, {"OMX_ComponentNameEnum", "SEC_OMX_ComponentNameEnum", 0}}, + {(void**)&p_GetHandle, {"OMX_GetHandle", "SEC_OMX_GetHandle", 0}}, + {(void**)&p_FreeHandle, {"OMX_FreeHandle", "SEC_OMX_FreeHandle", 0}} + }; + for (size_t i = 0; i < sizeof(sym_table)/sizeof(sym_table[0]); ++i) { + void** pf = sym_table[i].pf; + for (int j = 0; sym_table[i].names[j]; ++j) { + *pf = (void*)sLib.resolve(sym_table[i].names[j]); + } + if (!(*pf)) { + qWarning("OMX API not found: %s", sym_table[i].names[0]); + } + } +} + +OMX_ERRORTYPE core::OMX_Init() +{ + return p_Init(); +} + +OMX_ERRORTYPE core::OMX_Deinit() +{ + return p_Deinit(); +} + +OMX_ERRORTYPE core::OMX_ComponentNameEnum(OMX_STRING cComponentName, OMX_U32 nNameLength, OMX_U32 nIndex) +{ + return p_ComponentNameEnum(cComponentName, nNameLength, nIndex); +} + +OMX_ERRORTYPE core::OMX_GetHandle(OMX_HANDLETYPE* pHandle, OMX_STRING cComponentName, OMX_PTR pAppData, OMX_CALLBACKTYPE* pCallBacks) +{ + return p_GetHandle(pHandle, cComponentName, pAppData, pCallBacks); +} + +OMX_ERRORTYPE core::OMX_FreeHandle(OMX_HANDLETYPE hComponent) +{ + return p_FreeHandle(hComponent); +} + +} //namespace omx +} //namespace QtAV diff --git a/src/openmax/OMXHelper.h b/src/openmax/OMXHelper.h new file mode 100644 index 00000000..35f40528 --- /dev/null +++ b/src/openmax/OMXHelper.h @@ -0,0 +1,59 @@ +/****************************************************************************** + QtAV: Multimedia framework based on Qt and FFmpeg + Copyright (C) 2012-2016 Wang Bin + +* This file is part of QtAV (from 2016) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +******************************************************************************/ + +#include +#include + +#define OMX_ENSURE(f, ...) do { \ + OMX_ERRORTYPE err = f; \ + if (err != OMX_ErrorNone) { \ + qWarning("OMX error (%d) - " #f , err); \ + return __VA_ARGS__; \ + } \ +} while(0) + +#define OMX_WARN(f) do { \ + OMX_ERRORTYPE err = f; \ + if (err != OMX_ErrorNone) { \ + qWarning("OMX error (%d) - " #f , err); \ + } \ +} while(0) + +namespace QtAV { +namespace omx { + +class core +{ +public: + core(); + OMX_ERRORTYPE OMX_Init(); + OMX_ERRORTYPE OMX_Deinit(); + OMX_ERRORTYPE OMX_ComponentNameEnum(OMX_STRING cComponentName, OMX_U32 nNameLength, OMX_U32 nIndex); + OMX_ERRORTYPE OMX_GetHandle(OMX_HANDLETYPE* pHandle, OMX_STRING cComponentName, OMX_PTR pAppData, OMX_CALLBACKTYPE* pCallBacks); + OMX_ERRORTYPE OMX_FreeHandle(OMX_HANDLETYPE hComponent); +}; + +class componet : protected core +{ +public: +}; +} //namespace omx +} //namespace QtAV