ALT Linux Bugzilla
– Attachment 6376 Details for
Bug 30920
Вернуть поддержку crystalhd
New bug
|
Search
|
[?]
|
Help
Register
|
Log In
[x]
|
Forgot Password
Login:
[x]
|
EN
|
RU
[patch]
kodi-15.1-crystalhd.patch
kodi-15.1-crystalhd.patch (text/plain), 86.89 KB, created by
Zerg
on 2015-09-23 11:58:14 MSK
(
hide
)
Description:
kodi-15.1-crystalhd.patch
Filename:
MIME Type:
Creator:
Zerg
Created:
2015-09-23 11:58:14 MSK
Size:
86.89 KB
patch
obsolete
>--- kodi-15.1~/configure.ac 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/configure.ac 2015-09-19 18:10:44.239613035 +0300 >@@ -200,6 +200,8 @@ vdpau_not_found="== Could not find libvd > vdpau_disabled="== VDPAU support manually disabled. ==" > vaapi_not_found="== Could not find libva. VAAPI support disabled. ==" > vaapi_disabled="== VAAPI support manually disabled. ==" >+crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. ==" >+crystalhd_disabled="== CrystalHD support manually disabled. ==" > vtbdecoder_enabled="== VTBDecoder support enabled. ==" > vtbdecoder_disabled="== VTBDecoder support manually disabled. ==" > openmax_disabled="== OpenMax support manually disabled. ==" >@@ -286,6 +288,12 @@ AC_ARG_ENABLE([vaapi], > [use_vaapi=$enableval], > [use_vaapi=auto]) > >+AC_ARG_ENABLE([crystalhd], >+ [AS_HELP_STRING([--enable-crystalhd], >+ [enable CrystalHD decoding (default is auto)])], >+ [use_crystalhd=$enableval], >+ [use_crystalhd=auto]) >+ > AC_ARG_ENABLE([vtbdecoder], > [AS_HELP_STRING([--enable-vtbdecoder], > [enable VTBDecoder decoding (default is auto)])], >@@ -645,6 +653,7 @@ case $host in > use_joystick=no > use_neon=yes > use_libcec=no >+ use_crystalhd=no > use_vtbdecoder=yes > use_optical_drive=no > use_dvdcss=no >@@ -669,6 +678,7 @@ case $host in > ;; > powerpc-apple-darwin*) > use_joystick=no >+ use_crystalhd=no > use_vtbdecoder=no > ARCH="powerpc-osx" > use_arch="ppc" >@@ -1881,6 +1891,41 @@ else > USE_VAAPI=0 > fi > >+# CrystalHD >+if test "x$use_crystalhd" != "xno"; then >+ SAVE_CFLAGS="$CFLAGS" >+ CFLAGS="-D__LINUX_USER__" >+ AC_CHECK_HEADER([libcrystalhd/libcrystalhd_if.h], [], >+ [ if test "x$use_crystalhd" = "xyes"; then >+ AC_MSG_ERROR($crystalhd_not_found) >+ else >+ use_crystalhd=no >+ AC_MSG_RESULT($crystalhd_not_found) >+ fi >+ USE_CRYSTALHD=0 >+ ]) >+ CFLAGS="$SAVE_CFLAGS" >+ if test "$host_vendor" != "apple"; then >+ XB_FIND_SONAME([CRYSTALHD], [crystalhd], [use_crystalhd]) >+ fi >+ if test "x$use_crystalhd" != "xno"; then >+ SAVE_CFLAGS="$CFLAGS" >+ CFLAGS="-D__LINUX_USER__ -lcrystalhd" >+ # check for new crystalhd lib >+ AC_COMPILE_IFELSE( >+ [AC_LANG_SOURCE([#include <libcrystalhd/bc_dts_types.h> >+ #include <libcrystalhd/bc_dts_defs.h> >+ PBC_INFO_CRYSTAL bCrystalInfo;])], >+ [ AC_DEFINE([HAVE_LIBCRYSTALHD], [2], [Define to 2 if you have the 'New Broadcom Crystal HD' library.]) ], >+ [ AC_DEFINE([HAVE_LIBCRYSTALHD], [1], [Define to 1 if you have the 'Old Broadcom Crystal HD' library.]) ]) >+ CFLAGS="$SAVE_CFLAGS" >+ USE_CRYSTALHD=1 >+ fi >+else >+ AC_MSG_NOTICE($crystalhd_disabled) >+ USE_CRYSTALHD=0 >+fi >+ > # VTBDecoder > if test "x$use_vtbdecoder" != "xno"; then > if test "$host_vendor" = "apple" ; then >@@ -2081,6 +2126,12 @@ else > final_message="$final_message\n VAAPI:\tNo" > fi > >+if test "x$use_crystalhd" != "xno"; then >+ final_message="$final_message\n CrystalHD:\tYes" >+else >+ final_message="$final_message\n CrystalHD:\tNo" >+fi >+ > if test "x$use_vtbdecoder" != "xno"; then > final_message="$final_message\n VTBDecoder:\tYes" > else >@@ -2612,6 +2663,7 @@ AC_SUBST(USE_OPENGL) > AC_SUBST(USE_OPENGLES) > AC_SUBST(USE_VDPAU) > AC_SUBST(USE_VAAPI) >+AC_SUBST(USE_CRYSTALHD) > AC_SUBST(USE_LIBSMBCLIENT) > AC_SUBST(USE_LIBNFS) > AC_SUBST(USE_AIRPLAY) >--- kodi-15.1~/system/settings/settings.xml 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/system/settings/settings.xml 2015-09-19 18:10:44.244612940 +0300 >@@ -786,6 +786,15 @@ > <default>true</default> > <control type="toggle" /> > </setting> >+ <setting id="videoplayer.usechd" type="boolean" label="13428" help="36159"> >+ <requirement>HasCrystalHDDevice</requirement> >+ <dependencies> >+ <dependency type="enable" setting="videoplayer.decodingmethod" operator="is">1</dependency> >+ </dependencies> >+ <level>2</level> >+ <default>true</default> >+ <control type="toggle" /> >+ </setting> > <setting id="videoplayer.useomxplayer" type="boolean" label="13458" help="13459"> > <requirement>HAS_OMXPLAYER</requirement> > <level>2</level> >--- kodi-15.1~/tools/depends/target/libcrystalhd/Makefile 1970-01-01 03:00:00.000000000 +0300 >+++ kodi-15.1/tools/depends/target/libcrystalhd/Makefile 2015-09-19 18:10:44.247612883 +0300 >@@ -0,0 +1,15 @@ >+include ../../Makefile.include >+DEPS= ../../Makefile.include >+ >+SOURCE=libcrystalhd >+ >+all: .installed-$(PLATFORM) >+ >+.installed-$(PLATFORM): $(SOURCE) >+ mkdir -p $(PREFIX)/include >+ cp -rf $(SOURCE) $(PREFIX)/include/ >+ touch $@ >+ >+clean: >+distclean:: >+ rm -f .installed-$(PLATFORM) >--- kodi-15.1~/tools/depends/target/Makefile 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/tools/depends/target/Makefile 2015-09-19 18:10:44.246612902 +0300 >@@ -27,12 +27,12 @@ endif > > ifeq ($(OS),ios) > DEPENDS += Backrow >- EXCLUDED_DEPENDS = libcec libusb >+ EXCLUDED_DEPENDS = libcec libusb libcrystalhd > endif > > ifeq ($(OS),osx) > DEPENDS += libGLEW libsdl >- EXCLUDED_DEPENDS = libusb >+ EXCLUDED_DEPENDS = libusb libcrystalhd > endif > > ifeq ($(OS),android) >--- kodi-15.1~/xbmc/Application.cpp 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/xbmc/Application.cpp 2015-09-19 18:10:44.256612711 +0300 >@@ -130,6 +130,9 @@ > #ifdef HAS_JSONRPC > #include "interfaces/json-rpc/JSONRPC.h" > #endif >+#if defined(HAVE_LIBCRYSTALHD) >+#include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h" >+#endif > #include "interfaces/AnnouncementManager.h" > #include "peripherals/Peripherals.h" > #include "peripherals/dialogs/GUIDialogPeripheralManager.h" >@@ -1215,6 +1218,10 @@ bool CApplication::Initialize() > > m_slowTimer.StartZero(); > >+#if defined(HAVE_LIBCRYSTALHD) >+ CCrystalHD::GetInstance(); >+#endif >+ > CAddonMgr::Get().StartServices(true); > > // configure seek handler >@@ -2665,6 +2672,10 @@ void CApplication::Stop(int exitCode) > XBMCHelper::GetInstance().Stop(); > #endif > >+#if defined(HAVE_LIBCRYSTALHD) >+ CCrystalHD::RemoveInstance(); >+#endif >+ > g_mediaManager.Stop(); > > // Stop services before unloading Python >--- kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp 2015-09-19 18:10:44.262612597 +0300 >@@ -42,6 +42,9 @@ > #endif > #include "Video/MMALCodec.h" > #include "Video/DVDVideoCodecStageFright.h" >+#if defined(HAVE_LIBCRYSTALHD) >+#include "Video/DVDVideoCodecCrystalHD.h" >+#endif > #if defined(HAS_LIBAMCODEC) > #include "utils/AMLUtils.h" > #include "Video/DVDVideoCodecAmlogic.h" >@@ -154,6 +157,11 @@ CDVDVideoCodec* CDVDFactoryCodec::Create > #elif defined(TARGET_DARWIN) > hwSupport += "VideoToolBoxDecoder:no "; > #endif >+#ifdef HAVE_LIBCRYSTALHD >+ hwSupport += "CrystalHD:yes "; >+#else >+ hwSupport += "CrystalHD:no "; >+#endif > #if defined(HAS_LIBAMCODEC) > hwSupport += "AMCodec:yes "; > #else >@@ -260,6 +268,30 @@ CDVDVideoCodec* CDVDFactoryCodec::Create > } > } > } >+#endif >+ >+#if defined(HAVE_LIBCRYSTALHD) >+ if (!hint.software && CSettings::Get().GetBool("videoplayer.usechd")) >+ { >+ if (CCrystalHD::GetInstance()->DevicePresent()) >+ { >+ switch(hint.codec) >+ { >+ case AV_CODEC_ID_VC1: >+ case AV_CODEC_ID_WMV3: >+ case AV_CODEC_ID_H264: >+ case AV_CODEC_ID_MPEG2VIDEO: >+ if (hint.codec == AV_CODEC_ID_H264 && hint.ptsinvalid) >+ break; >+ if (hint.codec == AV_CODEC_ID_MPEG2VIDEO && hint.width <= 720) >+ break; >+ if ( (pCodec = OpenCodec(new CDVDVideoCodecCrystalHD(), hint, options)) ) return pCodec; >+ break; >+ default: >+ break; >+ } >+ } >+ } > #endif > > #if defined(TARGET_ANDROID) >--- kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp 1970-01-01 03:00:00.000000000 +0300 >+++ kodi-15.1/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp 2015-09-19 18:10:44.269612464 +0300 >@@ -0,0 +1,2010 @@ >+/* >+ * Copyright (C) 2005-2013 Team XBMC >+ * http://xbmc.org >+ * >+ * 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 2, 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 XBMC; see the file COPYING. If not, see >+ * <http://www.gnu.org/licenses/>. >+ * >+ */ >+ >+#include "system.h" >+#if defined(TARGET_WINDOWS) >+#include "WIN32Util.h" >+#include "util.h" >+#include "dialogs/GUIDialogKaiToast.h" >+#include "guilib/LocalizeStrings.h" >+#endif >+ >+#if defined(HAVE_LIBCRYSTALHD) >+#include "CrystalHD.h" >+ >+#include "DVDClock.h" >+#include "DynamicDll.h" >+#include "utils/SystemInfo.h" >+#include "threads/Atomics.h" >+#include "threads/Thread.h" >+#include "utils/log.h" >+extern "C" { >+#include "libswscale/swscale.h" >+} >+#include "utils/TimeUtils.h" >+#include "windowing/WindowingFactory.h" >+#include "cores/FFmpeg.h" >+ >+namespace BCM >+{ >+ #if defined(TARGET_WINDOWS) >+ typedef void *HANDLE; >+ #else >+ #ifndef __LINUX_USER__ >+ #define __LINUX_USER__ >+ #endif >+ #endif >+ >+ #include <libcrystalhd/bc_dts_types.h> >+ #include <libcrystalhd/bc_dts_defs.h> >+ #include <libcrystalhd/libcrystalhd_if.h> >+}; >+ >+#define __MODULE_NAME__ "CrystalHD" >+//#define USE_CHD_SINGLE_THREADED_API >+class DllLibCrystalHDInterface >+{ >+public: >+ virtual ~DllLibCrystalHDInterface() {} >+ virtual BCM::BC_STATUS DtsDeviceOpen(void *hDevice, uint32_t mode)=0; >+ virtual BCM::BC_STATUS DtsDeviceClose(void *hDevice)=0; >+ virtual BCM::BC_STATUS DtsOpenDecoder(void *hDevice, uint32_t StreamType)=0; >+ virtual BCM::BC_STATUS DtsCloseDecoder(void *hDevice)=0; >+ virtual BCM::BC_STATUS DtsStartDecoder(void *hDevice)=0; >+ virtual BCM::BC_STATUS DtsSetVideoParams(void *hDevice, uint32_t videoAlg, int FGTEnable, int MetaDataEnable, int Progressive, uint32_t OptFlags)=0; >+ virtual BCM::BC_STATUS DtsStartCapture(void *hDevice)=0; >+ virtual BCM::BC_STATUS DtsFlushRxCapture(void *hDevice, int bDiscardOnly)=0; >+ virtual BCM::BC_STATUS DtsSetFFRate(void *hDevice, uint32_t rate)=0; >+ virtual BCM::BC_STATUS DtsGetDriverStatus(void *hDevice, BCM::BC_DTS_STATUS *pStatus)=0; >+ virtual BCM::BC_STATUS DtsProcInput(void *hDevice, uint8_t *pUserData, uint32_t ulSizeInBytes, uint64_t timeStamp, int encrypted)=0; >+ virtual BCM::BC_STATUS DtsProcOutput(void *hDevice, uint32_t milliSecWait, BCM::BC_DTS_PROC_OUT *pOut)=0; >+ virtual BCM::BC_STATUS DtsProcOutputNoCopy(void *hDevice, uint32_t milliSecWait, BCM::BC_DTS_PROC_OUT *pOut)=0; >+ virtual BCM::BC_STATUS DtsReleaseOutputBuffs(void *hDevice, void *Reserved, int fChange)=0; >+ virtual BCM::BC_STATUS DtsSetSkipPictureMode(void *hDevice, uint32_t Mode)=0; >+ virtual BCM::BC_STATUS DtsFlushInput(void *hDevice, uint32_t SkipMode)=0; >+ >+#if (HAVE_LIBCRYSTALHD == 2) >+ // new function calls, only present in new driver/library so manually load them >+ virtual BCM::BC_STATUS DtsGetVersion(void *hDevice, uint32_t *DrVer, uint32_t *DilVer)=0; >+ virtual BCM::BC_STATUS DtsSetInputFormat(void *hDevice, BCM::BC_INPUT_FORMAT *pInputFormat)=0; >+ virtual BCM::BC_STATUS DtsGetColorPrimaries(void *hDevice, uint32_t *colorPrimaries)=0; >+ virtual BCM::BC_STATUS DtsSetColorSpace(void *hDevice, BCM::BC_OUTPUT_FORMAT Mode422)=0; >+ virtual BCM::BC_STATUS DtsGetCapabilities(void *hDevice, BCM::BC_HW_CAPS *CapsBuffer)=0; >+ virtual BCM::BC_STATUS DtsSetScaleParams(void *hDevice, BCM::BC_SCALING_PARAMS *ScaleParams)=0; >+ virtual BCM::BC_STATUS DtsIsEndOfStream(void *hDevice, uint8_t* bEOS)=0; >+ virtual BCM::BC_STATUS DtsCrystalHDVersion(void *hDevice, BCM::BC_INFO_CRYSTAL *CrystalInfo)=0; >+#endif >+}; >+ >+class DllLibCrystalHD : public DllDynamic, DllLibCrystalHDInterface >+{ >+ DECLARE_DLL_WRAPPER(DllLibCrystalHD, DLL_PATH_LIBCRYSTALHD) >+ >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsDeviceOpen, (void *p1, uint32_t p2)) >+ DEFINE_METHOD1(BCM::BC_STATUS, DtsDeviceClose, (void *p1)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsOpenDecoder, (void *p1, uint32_t p2)) >+ DEFINE_METHOD1(BCM::BC_STATUS, DtsCloseDecoder, (void *p1)) >+ DEFINE_METHOD1(BCM::BC_STATUS, DtsStartDecoder, (void *p1)) >+ DEFINE_METHOD1(BCM::BC_STATUS, DtsStopDecoder, (void *p1)) >+ DEFINE_METHOD6(BCM::BC_STATUS, DtsSetVideoParams, (void *p1, uint32_t p2, int p3, int p4, int p5, uint32_t p6)) >+ DEFINE_METHOD1(BCM::BC_STATUS, DtsStartCapture, (void *p1)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsFlushRxCapture, (void *p1, int p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsSetFFRate, (void *p1, uint32_t p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsGetDriverStatus, (void *p1, BCM::BC_DTS_STATUS *p2)) >+ DEFINE_METHOD5(BCM::BC_STATUS, DtsProcInput, (void *p1, uint8_t *p2, uint32_t p3, uint64_t p4, int p5)) >+ DEFINE_METHOD3(BCM::BC_STATUS, DtsProcOutput, (void *p1, uint32_t p2, BCM::BC_DTS_PROC_OUT *p3)) >+ DEFINE_METHOD3(BCM::BC_STATUS, DtsProcOutputNoCopy,(void *p1, uint32_t p2, BCM::BC_DTS_PROC_OUT *p3)) >+ DEFINE_METHOD3(BCM::BC_STATUS, DtsReleaseOutputBuffs,(void *p1, void *p2, int p3)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsSetSkipPictureMode,(void *p1, uint32_t p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsFlushInput, (void *p1, uint32_t p2)) >+ >+#if (HAVE_LIBCRYSTALHD == 2) >+ DEFINE_METHOD3(BCM::BC_STATUS, DtsGetVersion, (void *p1, uint32_t *p2, uint32_t *p3)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsSetInputFormat, (void *p1, BCM::BC_INPUT_FORMAT *p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsGetColorPrimaries,(void *p1, uint32_t *p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsSetColorSpace, (void *p1, BCM::BC_OUTPUT_FORMAT p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsGetCapabilities, (void *p1, BCM::BC_HW_CAPS *p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsSetScaleParams, (void *p1, BCM::BC_SCALING_PARAMS *p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsIsEndOfStream, (void *p1, uint8_t *p2)) >+ DEFINE_METHOD2(BCM::BC_STATUS, DtsCrystalHDVersion,(void *p1, BCM::BC_INFO_CRYSTAL *p2)) >+#endif >+ >+ BEGIN_METHOD_RESOLVE() >+ RESOLVE_METHOD_RENAME(DtsDeviceOpen, DtsDeviceOpen) >+ RESOLVE_METHOD_RENAME(DtsDeviceClose, DtsDeviceClose) >+ RESOLVE_METHOD_RENAME(DtsOpenDecoder, DtsOpenDecoder) >+ RESOLVE_METHOD_RENAME(DtsCloseDecoder, DtsCloseDecoder) >+ RESOLVE_METHOD_RENAME(DtsStartDecoder, DtsStartDecoder) >+ RESOLVE_METHOD_RENAME(DtsStopDecoder, DtsStopDecoder) >+ RESOLVE_METHOD_RENAME(DtsSetVideoParams, DtsSetVideoParams) >+ RESOLVE_METHOD_RENAME(DtsStartCapture, DtsStartCapture) >+ RESOLVE_METHOD_RENAME(DtsFlushRxCapture, DtsFlushRxCapture) >+ RESOLVE_METHOD_RENAME(DtsSetFFRate, DtsSetFFRate) >+ RESOLVE_METHOD_RENAME(DtsGetDriverStatus, DtsGetDriverStatus) >+ RESOLVE_METHOD_RENAME(DtsProcInput, DtsProcInput) >+ RESOLVE_METHOD_RENAME(DtsProcOutput, DtsProcOutput) >+ RESOLVE_METHOD_RENAME(DtsProcOutputNoCopy,DtsProcOutputNoCopy) >+ RESOLVE_METHOD_RENAME(DtsReleaseOutputBuffs,DtsReleaseOutputBuffs) >+ RESOLVE_METHOD_RENAME(DtsSetSkipPictureMode,DtsSetSkipPictureMode) >+ RESOLVE_METHOD_RENAME(DtsFlushInput, DtsFlushInput) >+ END_METHOD_RESOLVE() >+ >+public: >+ bool LoadNewLibFunctions(void) >+ { >+#if (HAVE_LIBCRYSTALHD == 2) >+ int rtn; >+ rtn = m_dll->ResolveExport("DtsGetVersion", (void**)&m_DtsGetVersion_ptr, false); >+ rtn &= m_dll->ResolveExport("DtsSetInputFormat", (void**)&m_DtsSetInputFormat_ptr, false); >+ rtn &= m_dll->ResolveExport("DtsGetColorPrimaries",(void**)&m_DtsGetColorPrimaries_ptr, false); >+ rtn &= m_dll->ResolveExport("DtsSetColorSpace", (void**)&m_DtsSetColorSpace_ptr, false); >+ rtn &= m_dll->ResolveExport("DtsGetCapabilities", (void**)&m_DtsGetCapabilities_ptr, false); >+ rtn &= m_dll->ResolveExport("DtsSetScaleParams", (void**)&m_DtsSetScaleParams_ptr, false); >+ rtn &= m_dll->ResolveExport("DtsIsEndOfStream", (void**)&m_DtsIsEndOfStream_ptr, false); >+ rtn &= m_dll->ResolveExport("DtsCrystalHDVersion", (void**)&m_DtsCrystalHDVersion_ptr, false); >+ rtn &= m_dll->ResolveExport("DtsSetInputFormat", (void**)&m_DtsSetInputFormat_ptr, false); >+ return(rtn == 1); >+#else >+ return false; >+#endif >+ }; >+}; >+ >+void PrintFormat(BCM::BC_PIC_INFO_BLOCK &pib); >+void BcmDebugLog( BCM::BC_STATUS lResult, std::string strFuncName=""); >+ >+const char* g_DtsStatusText[] = { >+ "BC_STS_SUCCESS", >+ "BC_STS_INV_ARG", >+ "BC_STS_BUSY", >+ "BC_STS_NOT_IMPL", >+ "BC_STS_PGM_QUIT", >+ "BC_STS_NO_ACCESS", >+ "BC_STS_INSUFF_RES", >+ "BC_STS_IO_ERROR", >+ "BC_STS_NO_DATA", >+ "BC_STS_VER_MISMATCH", >+ "BC_STS_TIMEOUT", >+ "BC_STS_FW_CMD_ERR", >+ "BC_STS_DEC_NOT_OPEN", >+ "BC_STS_ERR_USAGE", >+ "BC_STS_IO_USER_ABORT", >+ "BC_STS_IO_XFR_ERROR", >+ "BC_STS_DEC_NOT_STARTED", >+ "BC_STS_FWHEX_NOT_FOUND", >+ "BC_STS_FMT_CHANGE", >+ "BC_STS_HIF_ACCESS", >+ "BC_STS_CMD_CANCELLED", >+ "BC_STS_FW_AUTH_FAILED", >+ "BC_STS_BOOTLOADER_FAILED", >+ "BC_STS_CERT_VERIFY_ERROR", >+ "BC_STS_DEC_EXIST_OPEN", >+ "BC_STS_PENDING", >+ "BC_STS_CLK_NOCHG" >+}; >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+class CMPCOutputThread : public CThread >+{ >+public: >+ CMPCOutputThread(void *device, DllLibCrystalHD *dll, bool has_bcm70015); >+ virtual ~CMPCOutputThread(); >+ >+ unsigned int GetReadyCount(void); >+ unsigned int GetFreeCount(void); >+ CPictureBuffer* ReadyListPop(void); >+ void FreeListPush(CPictureBuffer* pBuffer); >+ bool WaitOutput(unsigned int msec); >+ >+protected: >+ void DoFrameRateTracking(double timestamp); >+ void SetFrameRate(uint32_t resolution); >+ void SetAspectRatio(BCM::BC_PIC_INFO_BLOCK *pic_info); >+ void CopyOutAsNV12(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride); >+ void CopyOutAsNV12DeInterlace(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride); >+ void CopyOutAsYV12(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride); >+ void CopyOutAsYV12DeInterlace(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride); >+ void CheckUpperLeftGreenPixelHack(CPictureBuffer *pBuffer); >+ bool GetDecoderOutput(void); >+ virtual void Process(void); >+ >+ CSyncPtrQueue<CPictureBuffer> m_FreeList; >+ CSyncPtrQueue<CPictureBuffer> m_ReadyList; >+ >+ DllLibCrystalHD *m_dll; >+ void *m_device; >+ bool m_has_bcm70015; >+ unsigned int m_timeout; >+ bool m_format_valid; >+ bool m_is_live_stream; >+ int m_width; >+ int m_height; >+ uint64_t m_timestamp; >+ bool m_output_YV12; >+ uint64_t m_PictureNumber; >+ uint8_t m_color_space; >+ unsigned int m_color_range; >+ unsigned int m_color_matrix; >+ int m_interlace; >+ bool m_framerate_tracking; >+ uint64_t m_framerate_cnt; >+ double m_framerate_timestamp; >+ double m_framerate; >+ int m_aspectratio_x; >+ int m_aspectratio_y; >+ CEvent m_ready_event; >+ struct SwsContext *m_sw_scale_ctx; >+}; >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+#if defined(TARGET_DARWIN) >+#pragma mark - >+#endif >+CPictureBuffer::CPictureBuffer(ERenderFormat format, int width, int height) >+{ >+ m_width = width; >+ m_height = height; >+ m_field = CRYSTALHD_FIELD_FULL; >+ m_interlace = false; >+ m_timestamp = DVD_NOPTS_VALUE; >+ m_PictureNumber = 0; >+ m_color_space = BCM::MODE420; >+ m_color_range = 0; >+ m_color_matrix = 4; >+ m_format = format; >+ m_framerate = 0; >+ >+ switch(m_format) >+ { >+ default: >+ case RENDER_FMT_NV12: >+ // setup y plane >+ m_y_buffer_size = m_width * m_height; >+ m_y_buffer_ptr = (unsigned char*)_aligned_malloc(m_y_buffer_size, 16); >+ >+ m_u_buffer_size = 0; >+ m_v_buffer_size = 0; >+ m_u_buffer_ptr = NULL; >+ m_v_buffer_ptr = NULL; >+ m_uv_buffer_size = m_y_buffer_size / 2; >+ m_uv_buffer_ptr = (unsigned char*)_aligned_malloc(m_uv_buffer_size, 16); >+ break; >+ case RENDER_FMT_YUYV422: >+ // setup y plane >+ m_y_buffer_size = (2 * m_width) * m_height; >+ m_y_buffer_ptr = (unsigned char*)_aligned_malloc(m_y_buffer_size, 16); >+ >+ m_uv_buffer_size = 0; >+ m_uv_buffer_ptr = NULL; >+ m_u_buffer_size = 0; >+ m_v_buffer_size = 0; >+ m_u_buffer_ptr = NULL; >+ m_v_buffer_ptr = NULL; >+ break; >+ case RENDER_FMT_YUV420P: >+ // setup y plane >+ m_y_buffer_size = m_width * m_height; >+ m_y_buffer_ptr = (unsigned char*)_aligned_malloc(m_y_buffer_size, 16); >+ >+ m_uv_buffer_size = 0; >+ m_uv_buffer_ptr = NULL; >+ m_u_buffer_size = m_y_buffer_size / 4; >+ m_v_buffer_size = m_y_buffer_size / 4; >+ m_u_buffer_ptr = (unsigned char*)_aligned_malloc(m_u_buffer_size, 16); >+ m_v_buffer_ptr = (unsigned char*)_aligned_malloc(m_v_buffer_size, 16); >+ break; >+ } >+} >+ >+CPictureBuffer::~CPictureBuffer() >+{ >+ if (m_y_buffer_ptr) _aligned_free(m_y_buffer_ptr); >+ if (m_u_buffer_ptr) _aligned_free(m_u_buffer_ptr); >+ if (m_v_buffer_ptr) _aligned_free(m_v_buffer_ptr); >+ if (m_uv_buffer_ptr) _aligned_free(m_uv_buffer_ptr); >+} >+ >+///////////////////////////////////////////////////////////////////////////////////////////// >+#if defined(TARGET_DARWIN) >+#pragma mark - >+#endif >+CMPCOutputThread::CMPCOutputThread(void *device, DllLibCrystalHD *dll, bool has_bcm70015) : >+ CThread("MPCOutput"), >+ m_dll(dll), >+ m_device(device), >+ m_has_bcm70015(has_bcm70015), >+ m_timeout(20), >+ m_format_valid(false), >+ m_is_live_stream(false), >+ m_width(0), >+ m_height(0), >+ m_timestamp(0), >+ m_PictureNumber(0), >+ m_color_space(0), >+ m_color_range(0), >+ m_color_matrix(0), >+ m_interlace(0), >+ m_framerate_tracking(false), >+ m_framerate_cnt(0), >+ m_framerate_timestamp(0.0), >+ m_framerate(0.0), >+ m_aspectratio_x(1), >+ m_aspectratio_y(1) >+{ >+ m_sw_scale_ctx = NULL; >+ >+ if (g_Windowing.GetRenderQuirks() & RENDER_QUIRKS_YV12_PREFERED) >+ m_output_YV12 = true; >+ else >+ m_output_YV12 = false; >+} >+ >+CMPCOutputThread::~CMPCOutputThread() >+{ >+ while(m_ReadyList.Count()) >+ delete m_ReadyList.Pop(); >+ while(m_FreeList.Count()) >+ delete m_FreeList.Pop(); >+ >+ if (m_sw_scale_ctx) >+ sws_freeContext(m_sw_scale_ctx); >+} >+ >+unsigned int CMPCOutputThread::GetReadyCount(void) >+{ >+ return m_ReadyList.Count(); >+} >+ >+unsigned int CMPCOutputThread::GetFreeCount(void) >+{ >+ return m_FreeList.Count(); >+} >+ >+CPictureBuffer* CMPCOutputThread::ReadyListPop(void) >+{ >+ CPictureBuffer *pBuffer = m_ReadyList.Pop(); >+ return pBuffer; >+} >+ >+void CMPCOutputThread::FreeListPush(CPictureBuffer* pBuffer) >+{ >+ m_FreeList.Push(pBuffer); >+} >+ >+bool CMPCOutputThread::WaitOutput(unsigned int msec) >+{ >+ return m_ready_event.WaitMSec(msec); >+} >+ >+void CMPCOutputThread::DoFrameRateTracking(double timestamp) >+{ >+ if (timestamp != DVD_NOPTS_VALUE) >+ { >+ double duration; >+ // if timestamp does not start at a low value we >+ // came in the middle of an online live stream >+ // 250 ms is a fourth of a 25fps source >+ // if timestamp is larger than that at the beginning >+ // we are much more out of sync than with the rough >+ // calculation. To cover these 250 ms we need >+ // roughly 5 seconds of video stream to get back >+ // in sync >+ if (m_framerate_cnt == 0 && timestamp > 250000.0) >+ m_is_live_stream = true; >+ >+ duration = timestamp - m_framerate_timestamp; >+ if (duration > 0.0) >+ { >+ double framerate; >+ // cnt count has to be done here, cause we miss frames >+ // if framerate will not calculated correctly and >+ // duration has to be > 0.0 so we do not calc images twice >+ m_framerate_cnt++; >+ >+ m_framerate_timestamp += duration; >+ framerate = DVD_TIME_BASE / duration; >+ // qualify framerate, we don't care about absolute value, just >+ // want to to verify range. Timestamp could be borked so ignore >+ // anything that does not verify. >+ // 60, 59.94 -> 60 >+ // 50, 49.95 -> 50 >+ // 30, 29.97 -> 30 >+ // 25, 24.975 -> 25 >+ // 24, 23.976 -> 24 >+ switch ((int)(0.5 + framerate)) >+ { >+ case 60: >+ case 50: >+ case 30: >+ case 25: >+ case 24: >+ // if we have such a live stream framerate is more exact than calculating >+ // cause of m_framerate_cnt and timestamp do not match in any way >+ m_framerate = m_is_live_stream ? framerate : DVD_TIME_BASE / (m_framerate_timestamp/m_framerate_cnt); >+ break; >+ } >+ } >+ } >+} >+ >+void CMPCOutputThread::SetFrameRate(uint32_t resolution) >+{ >+ m_interlace = FALSE; >+ >+ switch (resolution) >+ { >+ case BCM::vdecRESOLUTION_1080p30: >+ m_framerate = 30.0; >+ break; >+ case BCM::vdecRESOLUTION_1080p29_97: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_1080p25 : >+ m_framerate = 25.0; >+ break; >+ case BCM::vdecRESOLUTION_1080p24: >+ m_framerate = 24.0; >+ break; >+ case BCM::vdecRESOLUTION_1080p23_976: >+ m_framerate = 24.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_1080p0: >+ // 1080p0 is ambiguious, could be 23.976 or 29.97 fps, decoder >+ // just does not know. 1080p@23_976 is more common but this >+ // will mess up 1080p@29_97 playback. We really need to verify >+ // which framerate with duration tracking. >+ m_framerate_tracking = true; >+ m_framerate = 24.0 * 1000.0 / 1001.0; >+ break; >+ >+ case BCM::vdecRESOLUTION_1080i29_97: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ m_interlace = TRUE; >+ break; >+ case BCM::vdecRESOLUTION_1080i0: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ m_interlace = TRUE; >+ break; >+ case BCM::vdecRESOLUTION_1080i: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ m_interlace = TRUE; >+ break; >+ case BCM::vdecRESOLUTION_1080i25: >+ m_framerate = 25.0 * 1000.0 / 1001.0; >+ m_interlace = TRUE; >+ break; >+ >+ case BCM::vdecRESOLUTION_720p59_94: >+ m_framerate = 60.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_720p: >+ m_framerate = 60.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_720p50: >+ m_framerate = 50.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_720p29_97: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_720p24: >+ m_framerate = 24.0; >+ break; >+ case BCM::vdecRESOLUTION_720p23_976: >+ // some 720p/25 will be identifed as this, enable tracking. >+ m_framerate_tracking = true; >+ m_framerate = 24.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_720p0: >+ // 720p0 is ambiguious, could be 23.976, 29.97 or 59.97 fps, decoder >+ // just does not know. 720p@23_976 is more common but this >+ // will mess up other playback. We really need to verify >+ // which framerate with duration tracking. >+ m_framerate_tracking = true; >+ m_framerate = 24.0 * 1000.0 / 1001.0; >+ break; >+ >+ case BCM::vdecRESOLUTION_576p25: >+ m_framerate = 25.0; >+ break; >+ case BCM::vdecRESOLUTION_576p0: >+ m_framerate = 25.0; >+ break; >+ case BCM::vdecRESOLUTION_PAL1: >+ m_framerate = 25.0 * 1000.0 / 1001.0; >+ m_interlace = TRUE; >+ break; >+ >+ case BCM::vdecRESOLUTION_480p0: >+ m_framerate = 60.0; >+ break; >+ case BCM::vdecRESOLUTION_480p: >+ m_framerate = 60.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_480p29_97: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ break; >+ case BCM::vdecRESOLUTION_480p23_976: >+ m_framerate = 24.0 * 1000.0 / 1001.0; >+ break; >+ >+ case BCM::vdecRESOLUTION_480i0: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ m_interlace = TRUE; >+ break; >+ case BCM::vdecRESOLUTION_480i: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ m_interlace = TRUE; >+ break; >+ case BCM::vdecRESOLUTION_NTSC: >+ m_framerate = 30.0 * 1000.0 / 1001.0; >+ m_interlace = TRUE; >+ break; >+ >+ default: >+ m_framerate_tracking = true; >+ m_framerate = 24.0 * 1000.0 / 1001.0; >+ break; >+ } >+ >+ CLog::Log(LOGDEBUG, "%s: resolution = %x interlace = %d", __MODULE_NAME__, resolution, m_interlace); >+} >+ >+void CMPCOutputThread::SetAspectRatio(BCM::BC_PIC_INFO_BLOCK *pic_info) >+{ >+ switch(pic_info->aspect_ratio) >+ { >+ case BCM::vdecAspectRatioSquare: >+ m_aspectratio_x = 1; >+ m_aspectratio_y = 1; >+ break; >+ case BCM::vdecAspectRatio12_11: >+ m_aspectratio_x = 12; >+ m_aspectratio_y = 11; >+ break; >+ case BCM::vdecAspectRatio10_11: >+ m_aspectratio_x = 10; >+ m_aspectratio_y = 11; >+ break; >+ case BCM::vdecAspectRatio16_11: >+ m_aspectratio_x = 16; >+ m_aspectratio_y = 11; >+ break; >+ case BCM::vdecAspectRatio40_33: >+ m_aspectratio_x = 40; >+ m_aspectratio_y = 33; >+ break; >+ case BCM::vdecAspectRatio24_11: >+ m_aspectratio_x = 24; >+ m_aspectratio_y = 11; >+ break; >+ case BCM::vdecAspectRatio20_11: >+ m_aspectratio_x = 20; >+ m_aspectratio_y = 11; >+ break; >+ case BCM::vdecAspectRatio32_11: >+ m_aspectratio_x = 32; >+ m_aspectratio_y = 11; >+ break; >+ case BCM::vdecAspectRatio80_33: >+ m_aspectratio_x = 80; >+ m_aspectratio_y = 33; >+ break; >+ case BCM::vdecAspectRatio18_11: >+ m_aspectratio_x = 18; >+ m_aspectratio_y = 11; >+ break; >+ case BCM::vdecAspectRatio15_11: >+ m_aspectratio_x = 15; >+ m_aspectratio_y = 11; >+ break; >+ case BCM::vdecAspectRatio64_33: >+ m_aspectratio_x = 64; >+ m_aspectratio_y = 33; >+ break; >+ case BCM::vdecAspectRatio160_99: >+ m_aspectratio_x = 160; >+ m_aspectratio_y = 99; >+ break; >+ case BCM::vdecAspectRatio4_3: >+ m_aspectratio_x = 4; >+ m_aspectratio_y = 3; >+ break; >+ case BCM::vdecAspectRatio16_9: >+ m_aspectratio_x = 16; >+ m_aspectratio_y = 9; >+ break; >+ case BCM::vdecAspectRatio221_1: >+ m_aspectratio_x = 221; >+ m_aspectratio_y = 1; >+ break; >+ case BCM::vdecAspectRatioUnknown: >+ m_aspectratio_x = 0; >+ m_aspectratio_y = 0; >+ break; >+ >+ case BCM::vdecAspectRatioOther: >+ m_aspectratio_x = pic_info->custom_aspect_ratio_width_height & 0x0000ffff; >+ m_aspectratio_y = pic_info->custom_aspect_ratio_width_height >> 16; >+ break; >+ } >+ if(m_aspectratio_x == 0) >+ { >+ m_aspectratio_x = 1; >+ m_aspectratio_y = 1; >+ } >+ >+ CLog::Log(LOGDEBUG, "%s: dec_par x = %d, dec_par y = %d", __MODULE_NAME__, m_aspectratio_x, m_aspectratio_y); >+} >+ >+void CMPCOutputThread::CopyOutAsYV12(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride) >+{ >+ // copy y >+ if (w == stride) >+ { >+ memcpy(pBuffer->m_y_buffer_ptr, procOut->Ybuff, w * h); >+ } >+ else >+ { >+ uint8_t *s_y = procOut->Ybuff; >+ uint8_t *d_y = pBuffer->m_y_buffer_ptr; >+ for (int y = 0; y < h; y++, s_y += stride, d_y += w) >+ memcpy(d_y, s_y, w); >+ } >+ //copy chroma >+ //copy uv packed to u,v planes (1/2 the width and 1/2 the height of y) >+ uint8_t *d_u = pBuffer->m_u_buffer_ptr; >+ uint8_t *d_v = pBuffer->m_v_buffer_ptr; >+ for (int y = 0; y < h/2; y++) >+ { >+ uint8_t *s_uv = procOut->UVbuff + (y * stride); >+ for (int x = 0; x < w/2; x++) >+ { >+ *d_u++ = *s_uv++; >+ *d_v++ = *s_uv++; >+ } >+ } >+} >+ >+void CMPCOutputThread::CopyOutAsYV12DeInterlace(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride) >+{ >+ // copy luma >+ uint8_t *s_y = procOut->Ybuff; >+ uint8_t *d_y = pBuffer->m_y_buffer_ptr; >+ for (int y = 0; y < h/2; y++, s_y += stride) >+ { >+ memcpy(d_y, s_y, w); >+ d_y += w; >+ memcpy(d_y, s_y, w); >+ d_y += w; >+ } >+ //copy chroma >+ //copy uv packed to u,v planes (1/2 the width and 1/2 the height of y) >+ uint8_t *d_u = pBuffer->m_u_buffer_ptr; >+ uint8_t *d_v = pBuffer->m_v_buffer_ptr; >+ for (int y = 0; y < h/4; y++) >+ { >+ uint8_t *s_uv = procOut->UVbuff + (y * stride); >+ for (int x = 0; x < w/2; x++) >+ { >+ *d_u++ = *s_uv++; >+ *d_v++ = *s_uv++; >+ } >+ s_uv = procOut->UVbuff + (y * stride); >+ for (int x = 0; x < w/2; x++) >+ { >+ *d_u++ = *s_uv++; >+ *d_v++ = *s_uv++; >+ } >+ } >+ >+ pBuffer->m_interlace = false; >+} >+ >+void CMPCOutputThread::CopyOutAsNV12(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride) >+{ >+ if (w == stride) >+ { >+ int bytes = w * h; >+ // copy y >+ memcpy(pBuffer->m_y_buffer_ptr, procOut->Ybuff, bytes); >+ // copy uv >+ memcpy(pBuffer->m_uv_buffer_ptr, procOut->UVbuff, bytes/2 ); >+ } >+ else >+ { >+ // copy y >+ uint8_t *s = procOut->Ybuff; >+ uint8_t *d = pBuffer->m_y_buffer_ptr; >+ for (int y = 0; y < h; y++, s += stride, d += w) >+ memcpy(d, s, w); >+ // copy uv >+ s = procOut->UVbuff; >+ d = pBuffer->m_uv_buffer_ptr; >+ for (int y = 0; y < h/2; y++, s += stride, d += w) >+ memcpy(d, s, w); >+ } >+} >+ >+void CMPCOutputThread::CopyOutAsNV12DeInterlace(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride) >+{ >+ // do simple line doubling de-interlacing. >+ // copy luma >+ uint8_t *s_y = procOut->Ybuff; >+ uint8_t *d_y = pBuffer->m_y_buffer_ptr; >+ for (int y = 0; y < h/2; y++, s_y += stride) >+ { >+ memcpy(d_y, s_y, w); >+ d_y += w; >+ memcpy(d_y, s_y, w); >+ d_y += w; >+ } >+ //copy chroma >+ uint8_t *s_uv = procOut->UVbuff; >+ uint8_t *d_uv = pBuffer->m_uv_buffer_ptr; >+ for (int y = 0; y < h/4; y++, s_uv += stride) { >+ memcpy(d_uv, s_uv, w); >+ d_uv += w; >+ memcpy(d_uv, s_uv, w); >+ d_uv += w; >+ } >+ pBuffer->m_interlace = false; >+} >+ >+void CMPCOutputThread::CheckUpperLeftGreenPixelHack(CPictureBuffer *pBuffer) >+{ >+ // crystalhd driver sends internal info in 1st pixel location, then restores >+ // original pixel value but sometimes, the info is broked and the >+ // driver cannot do the restore and zeros the pixel. This is wrong for >+ // yuv color space, uv values should be set to 128 otherwise we get a >+ // bright green pixel in upper left. >+ // We fix this by replicating the 2nd pixel to the 1st. >+ switch(pBuffer->m_format) >+ { >+ default: >+ case RENDER_FMT_YUV420P: >+ { >+ uint8_t *d_y = pBuffer->m_y_buffer_ptr; >+ uint8_t *d_u = pBuffer->m_u_buffer_ptr; >+ uint8_t *d_v = pBuffer->m_v_buffer_ptr; >+ d_y[0] = d_y[1]; >+ d_u[0] = d_u[1]; >+ d_v[0] = d_v[1]; >+ } >+ break; >+ >+ case RENDER_FMT_NV12: >+ { >+ uint8_t *d_y = pBuffer->m_y_buffer_ptr; >+ uint16_t *d_uv = (uint16_t*)pBuffer->m_uv_buffer_ptr; >+ d_y[0] = d_y[1]; >+ d_uv[0] = d_uv[1]; >+ } >+ break; >+ >+ case RENDER_FMT_YUYV422: >+ { >+ uint32_t *d_yuyv = (uint32_t*)pBuffer->m_y_buffer_ptr; >+ d_yuyv[0] = d_yuyv[1]; >+ } >+ break; >+ } >+} >+ >+bool CMPCOutputThread::GetDecoderOutput(void) >+{ >+ BCM::BC_STATUS ret; >+ BCM::BC_DTS_PROC_OUT procOut; >+ CPictureBuffer *pBuffer = NULL; >+ bool got_picture = false; >+ >+ // Setup output struct >+ memset(&procOut, 0, sizeof(BCM::BC_DTS_PROC_OUT)); >+ >+ // Fetch data from the decoder >+ ret = m_dll->DtsProcOutputNoCopy(m_device, m_timeout, &procOut); >+ >+ switch (ret) >+ { >+ case BCM::BC_STS_SUCCESS: >+ if (m_format_valid && (procOut.PoutFlags & BCM::BC_POUT_FLAGS_PIB_VALID)) >+ { >+ if (procOut.PicInfo.timeStamp && >+ m_timestamp != procOut.PicInfo.timeStamp && >+ m_width == (int)procOut.PicInfo.width && >+ m_height == (int)procOut.PicInfo.height) >+ { >+ m_timestamp = procOut.PicInfo.timeStamp; >+ m_PictureNumber = procOut.PicInfo.picture_number; >+ >+ if (m_framerate_tracking) >+ DoFrameRateTracking((double)m_timestamp / 1000.0); >+ >+ // do not let FreeList to get greater than 10 >+ if (m_FreeList.Count() > 10) >+ delete m_FreeList.Pop(); >+ >+ // Get next output buffer from the free list >+ pBuffer = m_FreeList.Pop(); >+ if (!pBuffer) >+ { >+ // No free pre-allocated buffers so make one >+ if (m_output_YV12) >+ { >+ // output YV12, nouveau driver has slow NV12, YUY2 capability. >+ pBuffer = new CPictureBuffer(RENDER_FMT_YUV420P, m_width, m_height); >+ } >+ else >+ { >+ if (m_color_space == BCM::MODE422_YUY2) >+ pBuffer = new CPictureBuffer(RENDER_FMT_YUYV422, m_width, m_height); >+ else >+ pBuffer = new CPictureBuffer(RENDER_FMT_NV12, m_width, m_height); >+ } >+ >+ CLog::Log(LOGDEBUG, "%s: Added a new Buffer, ReadyListCount: %d", __MODULE_NAME__, m_ReadyList.Count()); >+ while (!m_bStop && m_ReadyList.Count() > 10) >+ Sleep(1); >+ } >+ >+ pBuffer->m_width = m_width; >+ pBuffer->m_height = m_height; >+ pBuffer->m_field = CRYSTALHD_FIELD_FULL; >+ pBuffer->m_interlace = m_interlace > 0 ? true : false; >+ pBuffer->m_framerate = m_framerate; >+ pBuffer->m_timestamp = m_timestamp; >+ pBuffer->m_color_space = m_color_space; >+ pBuffer->m_color_range = m_color_range; >+ pBuffer->m_color_matrix = m_color_matrix; >+ pBuffer->m_PictureNumber = m_PictureNumber; >+ >+ int w = m_width; >+ int h = m_height; >+ // frame that are not equal in width to 720, 1280 or 1920 >+ // need to be copied by a quantized stride (possible lib/driver bug) so force it. >+ int stride = m_width; >+ if (!m_has_bcm70015) >+ { >+ // bcm70012 uses quantized strides >+ if (w <= 720) >+ stride = 720; >+ else if (w <= 1280) >+ stride = 1280; >+ else >+ stride = 1920; >+ } >+ >+ if (pBuffer->m_color_space == BCM::MODE420) >+ { >+ switch(pBuffer->m_format) >+ { >+ case RENDER_FMT_NV12: >+ if (pBuffer->m_interlace) >+ CopyOutAsNV12DeInterlace(pBuffer, &procOut, w, h, stride); >+ else >+ CopyOutAsNV12(pBuffer, &procOut, w, h, stride); >+ break; >+ case RENDER_FMT_YUV420P: >+ if (pBuffer->m_interlace) >+ CopyOutAsYV12DeInterlace(pBuffer, &procOut, w, h, stride); >+ else >+ CopyOutAsYV12(pBuffer, &procOut, w, h, stride); >+ break; >+ default: >+ break; >+ } >+ } >+ else >+ { >+ switch(pBuffer->m_format) >+ { >+ case RENDER_FMT_YUYV422: >+ if (pBuffer->m_interlace) >+ { >+ // do simple line doubling de-interlacing. >+ // copy luma >+ int yuy2_w = w * 2; >+ int yuy2_stride = stride*2; >+ uint8_t *s_y = procOut.Ybuff; >+ uint8_t *d_y = pBuffer->m_y_buffer_ptr; >+ for (int y = 0; y < h/2; y++, s_y += yuy2_stride) >+ { >+ memcpy(d_y, s_y, yuy2_w); >+ d_y += yuy2_w; >+ memcpy(d_y, s_y, yuy2_w); >+ d_y += yuy2_w; >+ } >+ pBuffer->m_interlace = false; >+ } >+ else >+ { >+ memcpy(pBuffer->m_y_buffer_ptr, procOut.Ybuff, pBuffer->m_y_buffer_size); >+ } >+ break; >+ case RENDER_FMT_YUV420P: >+ // TODO: deinterlace for yuy2 -> yv12, icky >+ { >+ // Perform the color space conversion. >+ uint8_t* src[] = { procOut.Ybuff, NULL, NULL, NULL }; >+ int srcStride[] = { stride*2, 0, 0, 0 }; >+ uint8_t* dst[] = { pBuffer->m_y_buffer_ptr, pBuffer->m_u_buffer_ptr, pBuffer->m_v_buffer_ptr, NULL }; >+ int dstStride[] = { pBuffer->m_width, pBuffer->m_width/2, pBuffer->m_width/2, 0 }; >+ >+ m_sw_scale_ctx = sws_getCachedContext(m_sw_scale_ctx, >+ pBuffer->m_width, pBuffer->m_height, PIX_FMT_YUYV422, >+ pBuffer->m_width, pBuffer->m_height, PIX_FMT_YUV420P, >+ SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL); >+ sws_scale(m_sw_scale_ctx, src, srcStride, 0, pBuffer->m_height, dst, dstStride); >+ } >+ break; >+ default: >+ break; >+ } >+ } >+ >+ CheckUpperLeftGreenPixelHack(pBuffer); >+ m_ReadyList.Push(pBuffer); >+ m_ready_event.Set(); >+ got_picture = true; >+ } >+ else >+ { >+ if (m_PictureNumber != procOut.PicInfo.picture_number) >+ CLog::Log(LOGDEBUG, "%s: No timestamp detected: %" PRIu64, __MODULE_NAME__, procOut.PicInfo.timeStamp); >+ m_PictureNumber = procOut.PicInfo.picture_number; >+ } >+ } >+ >+ m_dll->DtsReleaseOutputBuffs(m_device, NULL, FALSE); >+ break; >+ >+ case BCM::BC_STS_FMT_CHANGE: >+ CLog::Log(LOGDEBUG, "%s: Format Change Detected. Flags: 0x%08x", __MODULE_NAME__, procOut.PoutFlags); >+ if ((procOut.PoutFlags & BCM::BC_POUT_FLAGS_PIB_VALID) && (procOut.PoutFlags & BCM::BC_POUT_FLAGS_FMT_CHANGE)) >+ { >+ PrintFormat(procOut.PicInfo); >+ >+ if (procOut.PicInfo.height == 1088) { >+ procOut.PicInfo.height = 1080; >+ } >+ m_width = procOut.PicInfo.width; >+ m_height = procOut.PicInfo.height; >+ m_timestamp = DVD_NOPTS_VALUE; >+ m_color_space = procOut.b422Mode; >+ m_color_range = 0; >+ m_color_matrix = procOut.PicInfo.colour_primaries; >+ SetAspectRatio(&procOut.PicInfo); >+ SetFrameRate(procOut.PicInfo.frame_rate); >+ if (procOut.PicInfo.flags & VDEC_FLAG_INTERLACED_SRC) >+ { >+ m_interlace = true; >+ } >+ m_timeout = 2000; >+ m_format_valid = true; >+ m_ready_event.Set(); >+ } >+ break; >+ >+ case BCM::BC_STS_DEC_NOT_OPEN: >+ break; >+ >+ case BCM::BC_STS_DEC_NOT_STARTED: >+ break; >+ >+ case BCM::BC_STS_IO_USER_ABORT: >+ break; >+ >+ case BCM::BC_STS_NO_DATA: >+ break; >+ >+ case BCM::BC_STS_TIMEOUT: >+ break; >+ >+ default: >+ if (ret > 26) >+ CLog::Log(LOGDEBUG, "%s: DtsProcOutput returned %d.", __MODULE_NAME__, ret); >+ else >+ CLog::Log(LOGDEBUG, "%s: DtsProcOutput returned %s.", __MODULE_NAME__, g_DtsStatusText[ret]); >+ break; >+ } >+ >+ return got_picture; >+} >+ >+void CMPCOutputThread::Process(void) >+{ >+ BCM::BC_STATUS ret; >+ BCM::BC_DTS_STATUS decoder_status; >+ >+ m_PictureNumber = 0; >+ >+ CLog::Log(LOGDEBUG, "%s: Output Thread Started...", __MODULE_NAME__); >+ >+ // wait for decoder startup, calls into DtsProcOutputXXCopy will >+ // return immediately until decoder starts getting input packets. >+ while (!m_bStop) >+ { >+ memset(&decoder_status, 0, sizeof(decoder_status)); >+ ret = m_dll->DtsGetDriverStatus(m_device, &decoder_status); >+ if (ret == BCM::BC_STS_SUCCESS && decoder_status.ReadyListCount) >+ { >+ GetDecoderOutput(); >+ break; >+ } >+ Sleep(10); >+ } >+ >+ // decoder is primed so now calls in DtsProcOutputXXCopy will block >+ while (!m_bStop) >+ { >+ memset(&decoder_status, 0, sizeof(decoder_status)); >+ ret = m_dll->DtsGetDriverStatus(m_device, &decoder_status); >+ if (ret == BCM::BC_STS_SUCCESS && decoder_status.ReadyListCount != 0) >+ GetDecoderOutput(); >+ else >+ Sleep(1); >+ >+#ifdef USE_CHD_SINGLE_THREADED_API >+ while (!m_bStop) >+ { >+ ret = m_dll->DtsGetDriverStatus(m_device, &decoder_status); >+ if (ret == BCM::BC_STS_SUCCESS && decoder_status.ReadyListCount != 0) >+ { >+ double pts = (double)decoder_status.NextTimeStamp / 1000.0; >+ fprintf(stdout, "cpbEmptySize(%d), NextTimeStamp(%f)\n", decoder_status.cpbEmptySize, pts); >+ break; >+ } >+ Sleep(10); >+ } >+#endif >+ } >+ CLog::Log(LOGDEBUG, "%s: Output Thread Stopped...", __MODULE_NAME__); >+} >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+#if defined(TARGET_DARWIN) >+#pragma mark - >+#endif >+CCrystalHD* CCrystalHD::m_pInstance = NULL; >+ >+CCrystalHD::CCrystalHD() : >+ m_device(NULL), >+ m_device_preset(false), >+ m_new_lib(false), >+ m_decoder_open(false), >+ m_has_bcm70015(false), >+ m_color_space(BCM::MODE420), >+ m_drop_state(false), >+ m_skip_state(false), >+ m_timeout(0), >+ m_wait_timeout(0), >+ m_field(0), >+ m_width(0), >+ m_height(0), >+ m_reset(0), >+ m_last_pict_num(0), >+ m_last_demuxer_pts(0.0), >+ m_last_decoder_pts(0.0), >+ m_pOutputThread(NULL), >+ m_sps_pps_size(0), >+ m_convert_bitstream(false) >+{ >+#if (HAVE_LIBCRYSTALHD == 2) >+ memset(&m_bc_info_crystal, 0, sizeof(m_bc_info_crystal)); >+#endif >+ >+ memset(&m_chd_params, 0, sizeof(m_chd_params)); >+ memset(&m_sps_pps_context, 0, sizeof(m_sps_pps_context)); >+ >+ m_dll = new DllLibCrystalHD; >+#ifdef TARGET_WINDOWS >+ std::string strDll; >+ if(CWIN32Util::GetCrystalHDLibraryPath(strDll) && m_dll->SetFile(strDll) && m_dll->Load() && m_dll->IsLoaded() ) >+#else >+ if (m_dll->Load() && m_dll->IsLoaded() ) >+#endif >+ { >+#if (HAVE_LIBCRYSTALHD == 2) >+ m_new_lib = m_dll->LoadNewLibFunctions(); >+#endif >+ >+ OpenDevice(); >+ >+#if (HAVE_LIBCRYSTALHD == 2) >+ if (m_device && m_new_lib) >+ { >+ m_dll->DtsCrystalHDVersion(m_device, (BCM::PBC_INFO_CRYSTAL)&m_bc_info_crystal); >+ m_has_bcm70015 = (m_bc_info_crystal.device == 1); >+ // bcm70012 can do nv12 (420), yuy2 (422) and uyvy (422) >+ // bcm70015 can do only yuy2 (422) >+ if (m_has_bcm70015) >+ m_color_space = BCM::OUTPUT_MODE422_YUY2; >+ } >+#endif >+ } >+ >+ // delete dll if device open fails, minimizes ram footprint >+ if (!m_device) >+ { >+ delete m_dll; >+ m_dll = NULL; >+ CLog::Log(LOGDEBUG, "%s: broadcom crystal hd not found", __MODULE_NAME__); >+ } >+ else >+ { >+ // we know there's a device present now, close the device until doing playback >+ CloseDevice(); >+ } >+} >+ >+ >+CCrystalHD::~CCrystalHD() >+{ >+ if (m_decoder_open) >+ CloseDecoder(); >+ >+ if (m_device) >+ CloseDevice(); >+ >+ if (m_dll) >+ delete m_dll; >+} >+ >+ >+bool CCrystalHD::DevicePresent(void) >+{ >+ return m_device_preset; >+} >+ >+void CCrystalHD::RemoveInstance(void) >+{ >+ if (m_pInstance) >+ { >+ delete m_pInstance; >+ m_pInstance = NULL; >+ } >+} >+ >+CCrystalHD* CCrystalHD::GetInstance(void) >+{ >+ if (!m_pInstance) >+ { >+ m_pInstance = new CCrystalHD(); >+ } >+ return m_pInstance; >+} >+ >+void CCrystalHD::OpenDevice() >+{ >+ uint32_t mode = BCM::DTS_PLAYBACK_MODE | >+ BCM::DTS_LOAD_FILE_PLAY_FW | >+#ifdef USE_CHD_SINGLE_THREADED_API >+ BCM::DTS_SINGLE_THREADED_MODE | >+#endif >+ BCM::DTS_SKIP_TX_CHK_CPB | >+ BCM::DTS_PLAYBACK_DROP_RPT_MODE | >+ DTS_DFLT_RESOLUTION(BCM::vdecRESOLUTION_720p23_976); >+ >+ BCM::BC_STATUS res= m_dll->DtsDeviceOpen(&m_device, mode); >+ if (res != BCM::BC_STS_SUCCESS) >+ { >+ m_device = NULL; >+ if( res == BCM::BC_STS_DEC_EXIST_OPEN ) >+ CLog::Log(LOGDEBUG, "%s: device owned by another application", __MODULE_NAME__); >+ else >+ CLog::Log(LOGDEBUG, "%s: device open failed , returning(0x%x)", __MODULE_NAME__, res); >+ m_device_preset = false; >+ } >+ else >+ { >+ #if (HAVE_LIBCRYSTALHD == 2) >+ if (m_new_lib) >+ CLog::Log(LOGDEBUG, "%s(new API): device opened", __MODULE_NAME__); >+ else >+ CLog::Log(LOGDEBUG, "%s(old API): device opened", __MODULE_NAME__); >+ #else >+ CLog::Log(LOGDEBUG, "%s: device opened", __MODULE_NAME__); >+ #endif >+ m_device_preset = true; >+ } >+} >+ >+void CCrystalHD::CloseDevice() >+{ >+ if (m_device) >+ { >+ m_dll->DtsDeviceClose(m_device); >+ m_device = NULL; >+ CLog::Log(LOGDEBUG, "%s: device closed", __MODULE_NAME__); >+ } >+} >+ >+bool CCrystalHD::OpenDecoder(CRYSTALHD_CODEC_TYPE codec_type, CDVDStreamInfo &hints) >+{ >+ BCM::BC_STATUS res; >+ uint32_t StreamType; >+#if (HAVE_LIBCRYSTALHD == 2) >+ BCM::BC_MEDIA_SUBTYPE Subtype; >+#endif >+ >+ if (!m_device_preset) >+ return false; >+ >+ if (m_decoder_open) >+ CloseDecoder(); >+ >+ OpenDevice(); >+ if (!m_device) >+ return false; >+ >+#if (HAVE_LIBCRYSTALHD == 2) && defined(TARGET_WINDOWS) >+ // Drivers prior to 3.6.9.32 don't have proper support for CRYSTALHD_CODEC_ID_AVC1 >+ // The internal version numbers are different for some reason... >+ if ( (m_bc_info_crystal.dilVersion.dilRelease < 3) >+ || (m_bc_info_crystal.dilVersion.dilRelease == 3 && m_bc_info_crystal.dilVersion.dilMajor < 22) >+ || (m_bc_info_crystal.drvVersion.drvRelease < 3) >+ || (m_bc_info_crystal.drvVersion.drvRelease == 3 && m_bc_info_crystal.drvVersion.drvMajor < 7) ) >+ { >+ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, "CrystalHD", g_localizeStrings.Get(2101)); >+ CLog::Log(LOGWARNING, "CrystalHD drivers too old, please upgrade to 3.6.9 or later. Make sure to uninstall the old version first or the upgrade won't work."); >+ >+ if (codec_type == CRYSTALHD_CODEC_ID_AVC1) >+ return false; >+ } >+#endif >+ >+ uint32_t videoAlg = 0; >+ switch (codec_type) >+ { >+ case CRYSTALHD_CODEC_ID_VC1: >+ videoAlg = BCM::BC_VID_ALGO_VC1; >+ StreamType = BCM::BC_STREAM_TYPE_ES; >+ m_convert_bitstream = false; >+ break; >+ case CRYSTALHD_CODEC_ID_WVC1: >+ videoAlg = BCM::BC_VID_ALGO_VC1MP; >+ StreamType = BCM::BC_STREAM_TYPE_ES; >+ m_convert_bitstream = false; >+ break; >+ case CRYSTALHD_CODEC_ID_WMV3: >+ if (!m_has_bcm70015) >+ return false; >+ videoAlg = BCM::BC_VID_ALGO_VC1MP; >+ StreamType = BCM::BC_STREAM_TYPE_ES; >+ m_convert_bitstream = false; >+ break; >+ case CRYSTALHD_CODEC_ID_H264: >+ videoAlg = BCM::BC_VID_ALGO_H264; >+ StreamType = BCM::BC_STREAM_TYPE_ES; >+ m_convert_bitstream = false; >+ break; >+ case CRYSTALHD_CODEC_ID_AVC1: >+ videoAlg = BCM::BC_VID_ALGO_H264; >+ StreamType = BCM::BC_STREAM_TYPE_ES; >+ if (!m_new_lib) >+ m_convert_bitstream = bitstream_convert_init((uint8_t*)hints.extradata, hints.extrasize); >+ else >+ m_convert_bitstream = false; >+ break; >+ case CRYSTALHD_CODEC_ID_MPEG2: >+ videoAlg = BCM::BC_VID_ALGO_MPEG2; >+ StreamType = BCM::BC_STREAM_TYPE_ES; >+ m_convert_bitstream = false; >+ break; >+ //BC_VID_ALGO_DIVX: >+ //BC_VID_ALGO_VC1MP: >+ default: >+ return false; >+ break; >+ } >+ >+#if (HAVE_LIBCRYSTALHD == 2) >+ uint8_t *pMetaData = NULL; >+ uint32_t metaDataSz = 0; >+ uint32_t startCodeSz = 4; >+ m_chd_params.sps_pps_buf = NULL; >+ switch (codec_type) >+ { >+ case CRYSTALHD_CODEC_ID_VC1: >+ Subtype = BCM::BC_MSUBTYPE_VC1; >+ pMetaData = (uint8_t*)hints.extradata; >+ metaDataSz = hints.extrasize; >+ break; >+ case CRYSTALHD_CODEC_ID_WVC1: >+ Subtype = BCM::BC_MSUBTYPE_WVC1; >+ break; >+ case CRYSTALHD_CODEC_ID_WMV3: >+ Subtype = BCM::BC_MSUBTYPE_WMV3; >+ pMetaData = (uint8_t*)hints.extradata; >+ metaDataSz = hints.extrasize; >+ break; >+ case CRYSTALHD_CODEC_ID_H264: >+ Subtype = BCM::BC_MSUBTYPE_H264; >+ pMetaData = (uint8_t*)hints.extradata; >+ metaDataSz = hints.extrasize; >+ break; >+ case CRYSTALHD_CODEC_ID_AVC1: >+ Subtype = BCM::BC_MSUBTYPE_AVC1; >+ m_chd_params.sps_pps_buf = (uint8_t*)malloc(1000); >+ if (!extract_sps_pps_from_avcc(hints.extrasize, hints.extradata)) >+ { >+ free(m_chd_params.sps_pps_buf); >+ m_chd_params.sps_pps_buf = NULL; >+ } >+ else >+ { >+ pMetaData = m_chd_params.sps_pps_buf; >+ metaDataSz = m_chd_params.sps_pps_size; >+ startCodeSz = m_chd_params.nal_size_bytes; >+ } >+ break; >+ case CRYSTALHD_CODEC_ID_MPEG2: >+ Subtype = BCM::BC_MSUBTYPE_MPEG2VIDEO; >+ pMetaData = (uint8_t*)hints.extradata; >+ metaDataSz = hints.extrasize; >+ break; >+ //BC_VID_ALGO_DIVX: >+ //BC_VID_ALGO_VC1MP: >+ } >+#endif >+ >+ do >+ { >+#if (HAVE_LIBCRYSTALHD == 2) >+ if (m_new_lib) >+ { >+ BCM::BC_INPUT_FORMAT bcm_input_format; >+ memset(&bcm_input_format, 0, sizeof(BCM::BC_INPUT_FORMAT)); >+ >+ bcm_input_format.FGTEnable = FALSE; >+ bcm_input_format.Progressive = TRUE; >+ bcm_input_format.OptFlags = 0x80000000 | BCM::vdecFrameRate23_97; >+ #ifdef USE_CHD_SINGLE_THREADED_API >+ bcm_input_format.OptFlags |= 0x80; >+ #endif >+ >+ bcm_input_format.width = hints.width; >+ bcm_input_format.height = hints.height; >+ bcm_input_format.mSubtype = Subtype; >+ bcm_input_format.pMetaData = pMetaData; >+ bcm_input_format.metaDataSz = metaDataSz; >+ bcm_input_format.startCodeSz = startCodeSz; >+ >+ res = m_dll->DtsSetInputFormat(m_device, &bcm_input_format); >+ if (res != BCM::BC_STS_SUCCESS) >+ { >+ CLog::Log(LOGERROR, "%s: set input format failed", __MODULE_NAME__); >+ break; >+ } >+ >+ res = m_dll->DtsOpenDecoder(m_device, StreamType); >+ if (res != BCM::BC_STS_SUCCESS) >+ { >+ CLog::Log(LOGERROR, "%s: open decoder failed", __MODULE_NAME__); >+ break; >+ } >+ >+ if (m_has_bcm70015) >+ res = m_dll->DtsSetColorSpace(m_device, BCM::OUTPUT_MODE422_YUY2); >+ else >+ res = m_dll->DtsSetColorSpace(m_device, BCM::OUTPUT_MODE420); >+ if (res != BCM::BC_STS_SUCCESS) >+ { >+ CLog::Log(LOGERROR, "%s: set color space failed", __MODULE_NAME__); >+ break; >+ } >+ } >+ else >+#endif >+ { >+ res = m_dll->DtsOpenDecoder(m_device, StreamType); >+ if (res != BCM::BC_STS_SUCCESS) >+ { >+ CLog::Log(LOGERROR, "%s: open decoder failed", __MODULE_NAME__); >+ break; >+ } >+ >+ uint32_t OptFlags = 0x80000000 | BCM::vdecFrameRate23_97; >+ res = m_dll->DtsSetVideoParams(m_device, videoAlg, FALSE, FALSE, TRUE, OptFlags); >+ if (res != BCM::BC_STS_SUCCESS) >+ { >+ CLog::Log(LOGERROR, "%s: set video params failed", __MODULE_NAME__); >+ break; >+ } >+ } >+ >+ res = m_dll->DtsStartDecoder(m_device); >+ if (res != BCM::BC_STS_SUCCESS) >+ { >+ CLog::Log(LOGERROR, "%s: start decoder failed", __MODULE_NAME__); >+ break; >+ } >+ >+ res = m_dll->DtsStartCapture(m_device); >+ if (res != BCM::BC_STS_SUCCESS) >+ { >+ CLog::Log(LOGERROR, "%s: start capture failed", __MODULE_NAME__); >+ break; >+ } >+ >+ m_pOutputThread = new CMPCOutputThread(m_device, m_dll, m_has_bcm70015); >+ m_pOutputThread->Create(); >+ >+ m_drop_state = false; >+ m_skip_state = false; >+ m_decoder_open = true; >+ // set output timeout to 1ms during startup, >+ // this will get reset once we get a picture back. >+ // the effect is to speed feeding demux packets during startup. >+ m_wait_timeout = 1; >+ m_reset = 0; >+ m_last_pict_num = 0; >+ m_last_demuxer_pts = DVD_NOPTS_VALUE; >+ m_last_decoder_pts = DVD_NOPTS_VALUE; >+ } while(false); >+ >+ return m_decoder_open; >+} >+ >+void CCrystalHD::CloseDecoder(void) >+{ >+ if (m_pOutputThread) >+ { >+ while(m_BusyList.Count()) >+ m_pOutputThread->FreeListPush( m_BusyList.Pop() ); >+ >+ m_pOutputThread->StopThread(); >+ delete m_pOutputThread; >+ m_pOutputThread = NULL; >+ } >+ >+ if (m_convert_bitstream) >+ { >+ if (m_sps_pps_context.sps_pps_data) >+ { >+ free(m_sps_pps_context.sps_pps_data); >+ m_sps_pps_context.sps_pps_data = NULL; >+ } >+ } >+#if (HAVE_LIBCRYSTALHD == 2) >+ if (m_chd_params.sps_pps_buf) >+ { >+ free(m_chd_params.sps_pps_buf); >+ m_chd_params.sps_pps_buf = NULL; >+ } >+#endif >+ >+ if (m_decoder_open) >+ { >+ // DtsFlushRxCapture must release internal queues when >+ // calling DtsStopDecoder/DtsCloseDecoder or the next >+ // DtsStartCapture will fail. This is a driver/lib bug >+ // with new chd driver. The existing driver ignores the >+ // bDiscardOnly arg. >+ if (!m_has_bcm70015) >+ m_dll->DtsFlushRxCapture(m_device, false); >+ m_dll->DtsStopDecoder(m_device); >+ m_dll->DtsCloseDecoder(m_device); >+ m_decoder_open = false; >+ } >+ >+ CloseDevice(); >+} >+ >+void CCrystalHD::Reset(void) >+{ >+ if (!m_has_bcm70015) >+ { >+ // Calling for non-error flush, Flushes all the decoder >+ // buffers, input, decoded and to be decoded. >+ m_reset = 10; >+ m_wait_timeout = 1; >+ m_dll->DtsFlushInput(m_device, 2); >+ } >+ >+ while (m_BusyList.Count()) >+ m_pOutputThread->FreeListPush( m_BusyList.Pop() ); >+ >+ while (m_pOutputThread->GetReadyCount()) >+ { >+ ::Sleep(1); >+ m_pOutputThread->FreeListPush( m_pOutputThread->ReadyListPop() ); >+ } >+} >+ >+bool CCrystalHD::AddInput(unsigned char *pData, size_t size, double dts, double pts) >+{ >+ if (pData) >+ { >+ BCM::BC_STATUS ret; >+ uint64_t int_pts = pts * 1000; >+ int demuxer_bytes = size; >+ uint8_t *demuxer_content = pData; >+ bool free_demuxer_content = false; >+ >+ if (m_convert_bitstream) >+ { >+ // convert demuxer packet from bitstream (AVC1) to bytestream (AnnexB) >+ int bytestream_size = 0; >+ uint8_t *bytestream_buff = NULL; >+ >+ bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size); >+ if (bytestream_buff && (bytestream_size > 0)) >+ { >+ if (bytestream_buff != demuxer_content) >+ free_demuxer_content = true; >+ demuxer_bytes = bytestream_size; >+ demuxer_content = bytestream_buff; >+ } >+ } >+ >+ do >+ { >+ ret = m_dll->DtsProcInput(m_device, demuxer_content, demuxer_bytes, int_pts, 0); >+ if (ret == BCM::BC_STS_SUCCESS) >+ { >+ m_last_demuxer_pts = pts; >+ } >+ else if (ret == BCM::BC_STS_BUSY) >+ { >+ CLog::Log(LOGDEBUG, "%s: DtsProcInput returned BC_STS_BUSY", __MODULE_NAME__); >+ ::Sleep(1); // Buffer is full, sleep it empty >+ } >+ } while (ret != BCM::BC_STS_SUCCESS); >+ >+ if (free_demuxer_content) >+ free(demuxer_content); >+ >+ if (!m_has_bcm70015) >+ { >+ if (m_reset) >+ { >+ m_reset--; >+ if (!m_skip_state) >+ { >+ m_skip_state = true; >+ m_dll->DtsSetSkipPictureMode(m_device, 1); >+ } >+ } >+ else >+ { >+ if (m_skip_state) >+ { >+ m_skip_state = false; >+ m_dll->DtsSetSkipPictureMode(m_device, 0); >+ } >+ } >+ } >+ >+ if (m_pOutputThread->GetReadyCount() < 1) >+ m_pOutputThread->WaitOutput(m_wait_timeout); >+ } >+ >+ return true; >+} >+ >+int CCrystalHD::GetReadyCount(void) >+{ >+ if (m_pOutputThread) >+ return m_pOutputThread->GetReadyCount(); >+ else >+ return 0; >+} >+ >+void CCrystalHD::BusyListFlush(void) >+{ >+ if (m_pOutputThread) >+ { >+ while ( m_BusyList.Count()) >+ m_pOutputThread->FreeListPush( m_BusyList.Pop() ); >+ } >+} >+ >+bool CCrystalHD::GetPicture(DVDVideoPicture *pDvdVideoPicture) >+{ >+ CPictureBuffer* pBuffer = m_pOutputThread->ReadyListPop(); >+ >+ if (!pBuffer) >+ return false; >+ >+ // default both dts/pts to DVD_NOPTS_VALUE, if crystalhd drops a frame, >+ // we can't tell so we can not track dts through the decoder or with >+ // and external queue. pts will get set from m_timestamp. >+ pDvdVideoPicture->dts = DVD_NOPTS_VALUE; >+ pDvdVideoPicture->pts = DVD_NOPTS_VALUE; >+ >+ if (pBuffer->m_timestamp != 0) >+ pDvdVideoPicture->pts = (double)pBuffer->m_timestamp / 1000.0; >+ >+ pDvdVideoPicture->iWidth = pBuffer->m_width; >+ pDvdVideoPicture->iHeight = pBuffer->m_height; >+ pDvdVideoPicture->iDisplayWidth = pBuffer->m_width; >+ pDvdVideoPicture->iDisplayHeight = pBuffer->m_height; >+ >+ switch(pBuffer->m_format) >+ { >+ default: >+ case RENDER_FMT_NV12: >+ // Y plane >+ pDvdVideoPicture->data[0] = (uint8_t*)pBuffer->m_y_buffer_ptr; >+ pDvdVideoPicture->iLineSize[0] = pBuffer->m_width; >+ // UV packed plane >+ pDvdVideoPicture->data[1] = (uint8_t*)pBuffer->m_uv_buffer_ptr; >+ pDvdVideoPicture->iLineSize[1] = pBuffer->m_width; >+ // unused >+ pDvdVideoPicture->data[2] = NULL; >+ pDvdVideoPicture->iLineSize[2] = 0; >+ break; >+ case RENDER_FMT_YUYV422: >+ // YUV packed plane >+ pDvdVideoPicture->data[0] = (uint8_t*)pBuffer->m_y_buffer_ptr; >+ pDvdVideoPicture->iLineSize[0] = pBuffer->m_width * 2; >+ // unused >+ pDvdVideoPicture->data[1] = NULL; >+ pDvdVideoPicture->iLineSize[1] = 0; >+ // unused >+ pDvdVideoPicture->data[2] = NULL; >+ pDvdVideoPicture->iLineSize[2] = 0; >+ break; >+ case RENDER_FMT_YUV420P: >+ // Y plane >+ pDvdVideoPicture->data[0] = (uint8_t*)pBuffer->m_y_buffer_ptr; >+ pDvdVideoPicture->iLineSize[0] = pBuffer->m_width; >+ // U plane >+ pDvdVideoPicture->data[1] = (uint8_t*)pBuffer->m_u_buffer_ptr; >+ pDvdVideoPicture->iLineSize[1] = pBuffer->m_width / 2; >+ // V plane >+ pDvdVideoPicture->data[2] = (uint8_t*)pBuffer->m_v_buffer_ptr; >+ pDvdVideoPicture->iLineSize[2] = pBuffer->m_width / 2; >+ break; >+ } >+ >+ pDvdVideoPicture->iRepeatPicture = 0; >+ pDvdVideoPicture->iDuration = DVD_TIME_BASE / pBuffer->m_framerate; >+ m_wait_timeout = pDvdVideoPicture->iDuration/2000; >+ pDvdVideoPicture->color_range = pBuffer->m_color_range; >+ pDvdVideoPicture->color_matrix = pBuffer->m_color_matrix; >+ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED; >+ pDvdVideoPicture->iFlags |= m_drop_state ? DVP_FLAG_DROPPED : 0; >+ pDvdVideoPicture->format = pBuffer->m_format; >+ >+ m_last_pict_num = pBuffer->m_PictureNumber; >+ m_last_decoder_pts = pDvdVideoPicture->pts; >+ >+ while( m_BusyList.Count()) >+ m_pOutputThread->FreeListPush( m_BusyList.Pop() ); >+ >+ m_BusyList.Push(pBuffer); >+ return true; >+} >+ >+void CCrystalHD::SetDropState(bool bDrop) >+{ >+ if (m_drop_state != bDrop) >+ { >+ m_drop_state = bDrop; >+ >+ if (!m_has_bcm70015) >+ { >+ if (!m_reset) >+ { >+ if (m_drop_state) >+ { >+ if (!m_skip_state) >+ { >+ m_skip_state = true; >+ m_dll->DtsSetSkipPictureMode(m_device, 1); >+ Sleep(1); >+ } >+ } >+ else >+ { >+ if (m_skip_state) >+ { >+ m_skip_state = false; >+ m_dll->DtsSetSkipPictureMode(m_device, 0); >+ Sleep(1); >+ } >+ } >+ } >+ } >+ } >+ /* >+ CLog::Log(LOGDEBUG, "%s: m_drop_state(%d), GetFreeCount(%d), GetReadyCount(%d)", __MODULE_NAME__, >+ m_drop_state, m_pOutputThread->GetFreeCount(), m_pOutputThread->GetReadyCount()); >+ */ >+} >+//////////////////////////////////////////////////////////////////////////////////////////// >+bool CCrystalHD::extract_sps_pps_from_avcc(int extradata_size, void *extradata) >+{ >+ // based on gstbcmdec.c (bcmdec_insert_sps_pps) >+ // which is Copyright(c) 2008 Broadcom Corporation. >+ // and Licensed LGPL 2.1 >+ >+ uint8_t *data = (uint8_t*)extradata; >+ uint32_t data_size = extradata_size; >+ int profile; >+ unsigned int nal_size; >+ unsigned int num_sps, num_pps; >+ >+ m_chd_params.sps_pps_size = 0; >+ >+ profile = (data[1] << 16) | (data[2] << 8) | data[3]; >+ CLog::Log(LOGDEBUG, "%s: profile %06x", __MODULE_NAME__, profile); >+ >+ m_chd_params.nal_size_bytes = (data[4] & 0x03) + 1; >+ >+ CLog::Log(LOGDEBUG, "%s: nal size %d", __MODULE_NAME__, m_chd_params.nal_size_bytes); >+ >+ num_sps = data[5] & 0x1f; >+ CLog::Log(LOGDEBUG, "%s: num sps %d", __MODULE_NAME__, num_sps); >+ >+ data += 6; >+ data_size -= 6; >+ >+ for (unsigned int i = 0; i < num_sps; i++) >+ { >+ if (data_size < 2) >+ return false; >+ >+ nal_size = (data[0] << 8) | data[1]; >+ data += 2; >+ data_size -= 2; >+ >+ if (data_size < nal_size) >+ return false; >+ >+ m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size + 0] = 0; >+ m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size + 1] = 0; >+ m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size + 2] = 0; >+ m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size + 3] = 1; >+ >+ m_chd_params.sps_pps_size += 4; >+ >+ memcpy(m_chd_params.sps_pps_buf + m_chd_params.sps_pps_size, data, nal_size); >+ m_chd_params.sps_pps_size += nal_size; >+ >+ data += nal_size; >+ data_size -= nal_size; >+ } >+ >+ if (data_size < 1) >+ return false; >+ >+ num_pps = data[0]; >+ data += 1; >+ data_size -= 1; >+ >+ for (unsigned int i = 0; i < num_pps; i++) >+ { >+ if (data_size < 2) >+ return false; >+ >+ nal_size = (data[0] << 8) | data[1]; >+ data += 2; >+ data_size -= 2; >+ >+ if (data_size < nal_size) >+ return false; >+ >+ m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size+0] = 0; >+ m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size+1] = 0; >+ m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size+2] = 0; >+ m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size+3] = 1; >+ >+ m_chd_params.sps_pps_size += 4; >+ >+ memcpy(m_chd_params.sps_pps_buf + m_chd_params.sps_pps_size, data, nal_size); >+ m_chd_params.sps_pps_size += nal_size; >+ >+ data += nal_size; >+ data_size -= nal_size; >+ } >+ >+ CLog::Log(LOGDEBUG, "%s: data size at end = %d ", __MODULE_NAME__, data_size); >+ >+ return true; >+} >+ >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+bool CCrystalHD::bitstream_convert_init(void *in_extradata, int in_extrasize) >+{ >+ // based on h264_mp4toannexb_bsf.c (ffmpeg) >+ // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> >+ // and Licensed GPL 2.1 or greater >+ >+ m_sps_pps_size = 0; >+ m_sps_pps_context.sps_pps_data = NULL; >+ >+ // nothing to filter >+ if (!in_extradata || in_extrasize < 6) >+ return false; >+ >+ uint16_t unit_size; >+ uint32_t total_size = 0; >+ uint8_t *out = NULL, unit_nb, sps_done = 0; >+ const uint8_t *extradata = (uint8_t*)in_extradata + 4; >+ static const uint8_t nalu_header[4] = {0, 0, 0, 1}; >+ >+ // retrieve length coded size >+ m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1; >+ if (m_sps_pps_context.length_size == 3) >+ return false; >+ >+ // retrieve sps and pps unit(s) >+ unit_nb = *extradata++ & 0x1f; // number of sps unit(s) >+ if (!unit_nb) >+ { >+ unit_nb = *extradata++; // number of pps unit(s) >+ sps_done++; >+ } >+ while (unit_nb--) >+ { >+ unit_size = extradata[0] << 8 | extradata[1]; >+ total_size += unit_size + 4; >+ if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) ) >+ { >+ free(out); >+ return false; >+ } >+ uint8_t* new_out = (uint8_t*)realloc(out, total_size); >+ if (new_out) >+ { >+ out = new_out; >+ } >+ else >+ { >+ CLog::Log(LOGERROR, "bitstream_convert_init failed - %s : could not realloc the buffer out", __FUNCTION__); >+ free(out); >+ return false; >+ } >+ >+ memcpy(out + total_size - unit_size - 4, nalu_header, 4); >+ memcpy(out + total_size - unit_size, extradata + 2, unit_size); >+ extradata += 2 + unit_size; >+ >+ if (!unit_nb && !sps_done++) >+ unit_nb = *extradata++; // number of pps unit(s) >+ } >+ >+ m_sps_pps_context.sps_pps_data = out; >+ m_sps_pps_context.size = total_size; >+ m_sps_pps_context.first_idr = 1; >+ >+ return true; >+} >+ >+bool CCrystalHD::bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size) >+{ >+ // based on h264_mp4toannexb_bsf.c (ffmpeg) >+ // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> >+ // and Licensed GPL 2.1 or greater >+ >+ uint8_t *buf = pData; >+ uint32_t buf_size = iSize; >+ uint8_t unit_type; >+ int32_t nal_size; >+ uint32_t cumul_size = 0; >+ const uint8_t *buf_end = buf + buf_size; >+ >+ do >+ { >+ if (buf + m_sps_pps_context.length_size > buf_end) >+ goto fail; >+ >+ if (m_sps_pps_context.length_size == 1) >+ nal_size = buf[0]; >+ else if (m_sps_pps_context.length_size == 2) >+ nal_size = buf[0] << 8 | buf[1]; >+ else >+ nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3]; >+ >+ buf += m_sps_pps_context.length_size; >+ unit_type = *buf & 0x1f; >+ >+ if (buf + nal_size > buf_end || nal_size < 0) >+ goto fail; >+ >+ // prepend only to the first type 5 NAL unit of an IDR picture >+ if (m_sps_pps_context.first_idr && unit_type == 5) >+ { >+ bitstream_alloc_and_copy(poutbuf, poutbuf_size, >+ m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size); >+ m_sps_pps_context.first_idr = 0; >+ } >+ else >+ { >+ bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size); >+ if (!m_sps_pps_context.first_idr && unit_type == 1) >+ m_sps_pps_context.first_idr = 1; >+ } >+ >+ buf += nal_size; >+ cumul_size += nal_size + m_sps_pps_context.length_size; >+ } while (cumul_size < buf_size); >+ >+ return true; >+ >+fail: >+ free(*poutbuf); >+ *poutbuf = NULL; >+ *poutbuf_size = 0; >+ return false; >+} >+ >+void CCrystalHD::bitstream_alloc_and_copy( >+ uint8_t **poutbuf, int *poutbuf_size, >+ const uint8_t *sps_pps, uint32_t sps_pps_size, >+ const uint8_t *in, uint32_t in_size) >+{ >+ // based on h264_mp4toannexb_bsf.c (ffmpeg) >+ // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr> >+ // and Licensed GPL 2.1 or greater >+ >+ #define CHD_WB32(p, d) { \ >+ ((uint8_t*)(p))[3] = (d); \ >+ ((uint8_t*)(p))[2] = (d) >> 8; \ >+ ((uint8_t*)(p))[1] = (d) >> 16; \ >+ ((uint8_t*)(p))[0] = (d) >> 24; } >+ >+ uint32_t offset = *poutbuf_size; >+ uint8_t nal_header_size = offset ? 3 : 4; >+ >+ *poutbuf_size += sps_pps_size + in_size + nal_header_size; >+ *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size); >+ if (sps_pps) >+ memcpy(*poutbuf + offset, sps_pps, sps_pps_size); >+ >+ memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size); >+ if (!offset) >+ { >+ CHD_WB32(*poutbuf + sps_pps_size, 1); >+ } >+ else >+ { >+ (*poutbuf + offset + sps_pps_size)[0] = 0; >+ (*poutbuf + offset + sps_pps_size)[1] = 0; >+ (*poutbuf + offset + sps_pps_size)[2] = 1; >+ } >+} >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+void PrintFormat(BCM::BC_PIC_INFO_BLOCK &pib) >+{ >+ CLog::Log(LOGDEBUG, "----------------------------------\n%s",""); >+ CLog::Log(LOGDEBUG, "\tTimeStamp: %" PRIu64"\n", pib.timeStamp); >+ CLog::Log(LOGDEBUG, "\tPicture Number: %d\n", pib.picture_number); >+ CLog::Log(LOGDEBUG, "\tWidth: %d\n", pib.width); >+ CLog::Log(LOGDEBUG, "\tHeight: %d\n", pib.height); >+ CLog::Log(LOGDEBUG, "\tChroma: 0x%03x\n", pib.chroma_format); >+ CLog::Log(LOGDEBUG, "\tPulldown: %d\n", pib.pulldown); >+ CLog::Log(LOGDEBUG, "\tFlags: 0x%08x\n", pib.flags); >+ CLog::Log(LOGDEBUG, "\tFrame Rate/Res: %d\n", pib.frame_rate); >+ CLog::Log(LOGDEBUG, "\tAspect Ratio: %d\n", pib.aspect_ratio); >+ CLog::Log(LOGDEBUG, "\tColor Primaries: %d\n", pib.colour_primaries); >+ CLog::Log(LOGDEBUG, "\tMetaData: %d\n", pib.picture_meta_payload); >+ CLog::Log(LOGDEBUG, "\tSession Number: %d\n", pib.sess_num); >+ CLog::Log(LOGDEBUG, "\tTimeStamp: %d\n", pib.ycom); >+ CLog::Log(LOGDEBUG, "\tCustom Aspect: %d\n", pib.custom_aspect_ratio_width_height); >+ CLog::Log(LOGDEBUG, "\tFrames to Drop: %d\n", pib.n_drop); >+ CLog::Log(LOGDEBUG, "\tH264 Valid Fields: 0x%08x\n", pib.other.h264.valid); >+} >+ >+#endif >--- kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.h 1970-01-01 03:00:00.000000000 +0300 >+++ kodi-15.1/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.h 2015-09-19 18:10:44.271612426 +0300 >@@ -0,0 +1,236 @@ >+#pragma once >+/* >+ * Copyright (C) 2005-2013 Team XBMC >+ * http://xbmc.org >+ * >+ * 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 2, 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 XBMC; see the file COPYING. If not, see >+ * <http://www.gnu.org/licenses/>. >+ * >+ */ >+ >+#if defined(HAVE_LIBCRYSTALHD) >+ >+#include <deque> >+ >+#include "DVDVideoCodec.h" >+#include "cores/dvdplayer/DVDStreamInfo.h" >+#include "threads/SingleLock.h" >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+template <class T> >+class CSyncPtrQueue >+{ >+public: >+ CSyncPtrQueue() { } >+ virtual ~CSyncPtrQueue() { } >+ void Push(T* p) >+ { >+ CSingleLock lock(m_Lock); >+ m_Queue.push_back(p); >+ } >+ >+ T* Pop() >+ { >+ T* p = NULL; >+ CSingleLock lock(m_Lock); >+ if (!m_Queue.empty()) >+ { >+ p = m_Queue.front(); >+ m_Queue.pop_front(); >+ } >+ return p; >+ } >+ unsigned int Count(){return m_Queue.size();} >+protected: >+ std::deque<T*> m_Queue; >+ CCriticalSection m_Lock; >+}; >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+class CPictureBuffer >+{ >+public: >+ CPictureBuffer(ERenderFormat format, int width, int height); >+ virtual ~CPictureBuffer(); >+ >+ unsigned int m_width; >+ unsigned int m_height; >+ unsigned int m_field; >+ bool m_interlace; >+ double m_framerate; >+ uint64_t m_timestamp; >+ int m_color_space; >+ unsigned int m_color_range; >+ unsigned int m_color_matrix; >+ uint64_t m_PictureNumber; >+ ERenderFormat m_format; >+ unsigned char *m_y_buffer_ptr; >+ unsigned char *m_u_buffer_ptr; >+ unsigned char *m_v_buffer_ptr; >+ unsigned char *m_uv_buffer_ptr; >+ int m_y_buffer_size; >+ int m_u_buffer_size; >+ int m_v_buffer_size; >+ int m_uv_buffer_size; >+}; >+ >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+enum _CRYSTALHD_CODEC_TYPES >+{ >+ CRYSTALHD_CODEC_ID_MPEG2 = 0, >+ CRYSTALHD_CODEC_ID_H264 = 1, >+ CRYSTALHD_CODEC_ID_AVC1 = 2, >+ CRYSTALHD_CODEC_ID_VC1 = 3, >+ CRYSTALHD_CODEC_ID_WMV3 = 4, >+ CRYSTALHD_CODEC_ID_WVC1 = 5, >+}; >+ >+typedef uint32_t CRYSTALHD_CODEC_TYPE; >+ >+#if (HAVE_LIBCRYSTALHD == 2) >+ >+ typedef struct _BC_INFO_CRYSTAL_ { >+ uint8_t device; >+ union { >+ struct { >+ uint32_t dilRelease:8; >+ uint32_t dilMajor:8; >+ uint32_t dilMinor:16; >+ }; >+ uint32_t version; >+ } dilVersion; >+ >+ union { >+ struct { >+ uint32_t drvRelease:4; >+ uint32_t drvMajor:8; >+ uint32_t drvMinor:12; >+ uint32_t drvBuild:8; >+ }; >+ uint32_t version; >+ } drvVersion; >+ >+ union { >+ struct { >+ uint32_t fwRelease:4; >+ uint32_t fwMajor:8; >+ uint32_t fwMinor:12; >+ uint32_t fwBuild:8; >+ }; >+ uint32_t version; >+ } fwVersion; >+ >+ uint32_t Reserved1; // For future expansion >+ uint32_t Reserved2; // For future expansion >+ } BC_INFO_CRYSTAL, *PBC_INFO_CRYSTAL; >+ >+#endif >+ >+//////////////////////////////////////////////////////////////////////////////////////////// >+ >+#define CRYSTALHD_FIELD_FULL 0x00 >+#define CRYSTALHD_FIELD_BOT 0x01 >+#define CRYSTALHD_FIELD_TOP 0x02 >+ >+typedef struct CHD_CODEC_PARAMS { >+ uint8_t *sps_pps_buf; >+ uint32_t sps_pps_size; >+ uint8_t nal_size_bytes; >+} CHD_CODEC_PARAMS; >+ >+class DllLibCrystalHD; >+class CMPCInputThread; >+class CMPCOutputThread; >+ >+class CCrystalHD >+{ >+public: >+ virtual ~CCrystalHD(); >+ >+ static void RemoveInstance(void); >+ static CCrystalHD* GetInstance(void); >+ >+ bool DevicePresent(void); >+ >+ void OpenDevice(); >+ void CloseDevice(); >+ >+ bool OpenDecoder(CRYSTALHD_CODEC_TYPE codec_type, CDVDStreamInfo &hints); >+ void CloseDecoder(void); >+ void Reset(void); >+ >+ bool AddInput(unsigned char *pData, size_t size, double dts, double pts); >+ >+ int GetReadyCount(void); >+ void BusyListFlush(void); >+ >+ bool GetPicture(DVDVideoPicture* pDvdVideoPicture); >+ void SetDropState(bool bDrop); >+ >+protected: >+ >+ DllLibCrystalHD *m_dll; >+ void *m_device; >+ bool m_device_preset; >+ bool m_new_lib; >+ bool m_decoder_open; >+ bool m_has_bcm70015; >+ int m_color_space; >+ bool m_drop_state; >+ bool m_skip_state; >+ unsigned int m_timeout; >+ unsigned int m_wait_timeout; >+ unsigned int m_field; >+ unsigned int m_width; >+ unsigned int m_height; >+ int m_reset; >+ int m_last_pict_num; >+ double m_last_demuxer_pts; >+ double m_last_decoder_pts; >+ >+ CMPCOutputThread *m_pOutputThread; >+ CSyncPtrQueue<CPictureBuffer> m_BusyList; >+#if (HAVE_LIBCRYSTALHD == 2) >+ BC_INFO_CRYSTAL m_bc_info_crystal; >+#endif >+ >+private: >+ CCrystalHD(); >+ CCrystalHD(const CCrystalHD& other); >+ CCrystalHD& operator=(const CCrystalHD&); >+ static CCrystalHD *m_pInstance; >+ >+ // bitstream to bytestream (Annex B) conversion support. >+ bool bitstream_convert_init(void *in_extradata, int in_extrasize); >+ bool bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size); >+ static void bitstream_alloc_and_copy( uint8_t **poutbuf, int *poutbuf_size, >+ const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size); >+ >+ typedef struct chd_bitstream_ctx { >+ uint8_t length_size; >+ uint8_t first_idr; >+ uint8_t *sps_pps_data; >+ uint32_t size; >+ } chd_bitstream_ctx; >+ >+ uint32_t m_sps_pps_size; >+ chd_bitstream_ctx m_sps_pps_context; >+ bool m_convert_bitstream; >+ >+ bool extract_sps_pps_from_avcc(int extradata_size, void *extradata); >+ CHD_CODEC_PARAMS m_chd_params; >+}; >+ >+#endif >--- kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.cpp 1970-01-01 03:00:00.000000000 +0300 >+++ kodi-15.1/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.cpp 2015-09-19 18:10:44.272612407 +0300 >@@ -0,0 +1,204 @@ >+/* >+ * Copyright (C) 2005-2013 Team XBMC >+ * http://xbmc.org >+ * >+ * 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 2, 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 XBMC; see the file COPYING. If not, see >+ * <http://www.gnu.org/licenses/>. >+ * >+ */ >+ >+#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS) >+ #include "config.h" >+#elif defined(TARGET_WINDOWS) >+#include "system.h" >+extern "C" { >+#include "libavcodec/avcodec.h" >+} >+#endif >+ >+#if defined(HAVE_LIBCRYSTALHD) >+#include "DVDClock.h" >+#include "DVDStreamInfo.h" >+#include "DVDVideoCodecCrystalHD.h" >+#include "settings/Settings.h" >+#include "utils/log.h" >+#include "utils/TimeUtils.h" >+ >+#define __MODULE_NAME__ "DVDVideoCodecCrystalHD" >+ >+CDVDVideoCodecCrystalHD::CDVDVideoCodecCrystalHD() : >+ m_Codec(NULL), >+ m_DropPictures(false), >+ m_Duration(0.0), >+ m_pFormatName(""), >+ m_CodecType(CRYSTALHD_CODEC_ID_MPEG2) >+{ >+} >+ >+CDVDVideoCodecCrystalHD::~CDVDVideoCodecCrystalHD() >+{ >+ Dispose(); >+} >+ >+bool CDVDVideoCodecCrystalHD::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options) >+{ >+ if (CSettings::Get().GetBool("videoplayer.usechd") && !hints.software) >+ { >+ switch (hints.codec) >+ { >+ case AV_CODEC_ID_MPEG2VIDEO: >+ m_CodecType = CRYSTALHD_CODEC_ID_MPEG2; >+ m_pFormatName = "chd-mpeg2"; >+ break; >+ case AV_CODEC_ID_H264: >+ switch(hints.profile) >+ { >+ case FF_PROFILE_H264_HIGH_10: >+ case FF_PROFILE_H264_HIGH_10_INTRA: >+ case FF_PROFILE_H264_HIGH_422: >+ case FF_PROFILE_H264_HIGH_422_INTRA: >+ case FF_PROFILE_H264_HIGH_444_PREDICTIVE: >+ case FF_PROFILE_H264_HIGH_444_INTRA: >+ case FF_PROFILE_H264_CAVLC_444: >+ CLog::Log(LOGNOTICE, "%s - unsupported h264 profile(%d)", __FUNCTION__, hints.profile); >+ return false; >+ break; >+ } >+ if (hints.extrasize < 7 || hints.extradata == NULL) >+ { >+ CLog::Log(LOGNOTICE, "%s - avcC atom too data small or missing", __FUNCTION__); >+ return false; >+ } >+ // valid avcC data (bitstream) always starts with the value 1 (version) >+ if ( *(char*)hints.extradata == 1 ) >+ m_CodecType = CRYSTALHD_CODEC_ID_AVC1; >+ else >+ m_CodecType = CRYSTALHD_CODEC_ID_H264; >+ >+ m_pFormatName = "chd-h264"; >+ break; >+ case AV_CODEC_ID_VC1: >+ m_CodecType = CRYSTALHD_CODEC_ID_VC1; >+ m_pFormatName = "chd-vc1"; >+ break; >+ case AV_CODEC_ID_WMV3: >+ m_CodecType = CRYSTALHD_CODEC_ID_WMV3; >+ m_pFormatName = "chd-wmv3"; >+ break; >+ default: >+ return false; >+ break; >+ } >+ >+ m_Codec = CCrystalHD::GetInstance(); >+ if (!m_Codec) >+ { >+ CLog::Log(LOGERROR, "%s: Failed to open Broadcom Crystal HD Codec", __MODULE_NAME__); >+ return false; >+ } >+ >+ if (m_Codec && !m_Codec->OpenDecoder(m_CodecType, hints)) >+ { >+ CLog::Log(LOGERROR, "%s: Failed to open Broadcom Crystal HD Codec", __MODULE_NAME__); >+ return false; >+ } >+ >+ // default duration to 23.976 fps, have to guess something. >+ m_Duration = (DVD_TIME_BASE / (24.0 * 1000.0/1001.0)); >+ m_DropPictures = false; >+ >+ CLog::Log(LOGINFO, "%s: Opened Broadcom Crystal HD Codec", __MODULE_NAME__); >+ return true; >+ } >+ >+ return false; >+} >+ >+void CDVDVideoCodecCrystalHD::Dispose(void) >+{ >+ if (m_Codec) >+ { >+ m_Codec->CloseDecoder(); >+ m_Codec = NULL; >+ } >+} >+ >+int CDVDVideoCodecCrystalHD::Decode(uint8_t *pData, int iSize, double dts, double pts) >+{ >+ if (!pData) >+ { >+ // if pData is nil, we are in dvdplayervideo's special loop >+ // where it checks for more picture frames, you must pass >+ // VC_BUFFER to get it to break out of this loop. >+ int ready_cnt = m_Codec->GetReadyCount(); >+ if (ready_cnt == 1) >+ return VC_PICTURE | VC_BUFFER; >+ if (ready_cnt > 2) >+ return VC_PICTURE; >+ else >+ return VC_BUFFER; >+ } >+ >+ // We are running a picture queue, picture frames are allocated >+ // in CrystalHD class if needed, then passed up. Need to return >+ // them back to CrystalHD class for re-queuing. This way we keep >+ // the memory alloc/free to a minimum and don't churn memory for >+ // each picture frame. >+ m_Codec->BusyListFlush(); >+ >+ if (pData) >+ { >+ // Handle Input, add demuxer packet to input queue, we must accept it or >+ // it will be discarded as DVDPlayerVideo has no concept of "try again". >+ if ( !m_Codec->AddInput(pData, iSize, dts, pts) ) >+ { >+ // Deep crap error, this should never happen unless we run away pulling demuxer pkts. >+ CLog::Log(LOGDEBUG, "%s: m_pInputThread->AddInput full.", __MODULE_NAME__); >+ Sleep(10); >+ } >+ } >+ >+ // if we have more than one frame ready, just return VC_PICTURE so >+ // dvdplayervideo will loop and drain them before sending another demuxer packet. >+ if (m_Codec->GetReadyCount() > 2) >+ return VC_PICTURE; >+ >+ int rtn = 0; >+ if (m_Codec->GetReadyCount()) >+ rtn = VC_PICTURE; >+ >+ return rtn | VC_BUFFER; >+} >+ >+void CDVDVideoCodecCrystalHD::Reset(void) >+{ >+ m_Codec->Reset(); >+} >+ >+bool CDVDVideoCodecCrystalHD::GetPicture(DVDVideoPicture* pDvdVideoPicture) >+{ >+ bool ret; >+ >+ ret = m_Codec->GetPicture(pDvdVideoPicture); >+ m_Duration = pDvdVideoPicture->iDuration; >+ return ret; >+} >+ >+void CDVDVideoCodecCrystalHD::SetDropState(bool bDrop) >+{ >+ m_DropPictures = bDrop; >+ m_Codec->SetDropState(m_DropPictures); >+} >+ >+#endif >--- kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.h 1970-01-01 03:00:00.000000000 +0300 >+++ kodi-15.1/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.h 2015-09-19 18:10:44.273612388 +0300 >@@ -0,0 +1,51 @@ >+/* >+ * Copyright (C) 2005-2013 Team XBMC >+ * http://xbmc.org >+ * >+ * 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 2, 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 XBMC; see the file COPYING. If not, see >+ * <http://www.gnu.org/licenses/>. >+ * >+ */ >+ >+#pragma once >+ >+#if defined(HAVE_LIBCRYSTALHD) >+ >+#include "CrystalHD.h" >+#include "DVDVideoCodec.h" >+ >+class CDVDVideoCodecCrystalHD : public CDVDVideoCodec >+{ >+public: >+ CDVDVideoCodecCrystalHD(); >+ virtual ~CDVDVideoCodecCrystalHD(); >+ >+ // Required overrides >+ virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options); >+ virtual void Dispose(void); >+ virtual int Decode(uint8_t *pData, int iSize, double dts, double pts); >+ virtual void Reset(void); >+ virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture); >+ virtual void SetDropState(bool bDrop); >+ virtual const char* GetName(void) { return (const char*)m_pFormatName; } >+ >+protected: >+ CCrystalHD *m_Codec; >+ bool m_DropPictures; >+ double m_Duration; >+ const char *m_pFormatName; >+ CRYSTALHD_CODEC_TYPE m_CodecType; >+}; >+ >+#endif >--- kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in 2015-09-19 18:10:44.273612388 +0300 >@@ -11,6 +11,10 @@ endif > ifeq (@USE_VAAPI@,1) > SRCS += VAAPI.cpp > endif >+ifeq (@USE_CRYSTALHD@,1) >+SRCS += CrystalHD.cpp >+SRCS += DVDVideoCodecCrystalHD.cpp >+endif > ifeq ($(findstring osx,@ARCH@),osx) > SRCS += DVDVideoCodecVDA.cpp > SRCS += VDA.cpp >--- kodi-15.1~/xbmc/DllPaths_generated.h.in 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/xbmc/DllPaths_generated.h.in 2015-09-19 18:10:44.258612673 +0300 >@@ -46,6 +46,13 @@ > #define DLL_PATH_LIBDVDNAV "special://xbmcbin/system/players/dvdplayer/libdvdnav-@ARCH@.so" > #define DLL_PATH_LIBMPEG2 "@MPEG2_SONAME@" > >+/* broadcom crystalhd */ >+#if defined(TARGET_DARWIN) >+#define DLL_PATH_LIBCRYSTALHD "libcrystalhd.dylib" >+#else >+#define DLL_PATH_LIBCRYSTALHD "@CRYSTALHD_SONAME@" >+#endif >+ > /* libbluray */ > #define DLL_PATH_LIBBLURAY "@BLURAY_SONAME@" > >--- kodi-15.1~/xbmc/settings/SettingConditions.cpp 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/xbmc/settings/SettingConditions.cpp 2015-09-19 18:10:44.275612349 +0300 >@@ -29,6 +29,9 @@ > #include "android/activity/AndroidFeatures.h" > #endif // defined(TARGET_ANDROID) > #include "cores/AudioEngine/AEFactory.h" >+#if defined(HAVE_LIBCRYSTALHD) >+#include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h" >+#endif // defined(HAVE_LIBCRYSTALHD) > #include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h" > #include "guilib/LocalizeStrings.h" > #include "peripherals/Peripherals.h" >@@ -224,6 +227,11 @@ void CSettingConditions::Initialize() > #ifdef HAS_ZEROCONF > m_simpleConditions.insert("has_zeroconf"); > #endif >+#ifdef HAVE_LIBCRYSTALHD >+ m_simpleConditions.insert("have_libcrystalhd"); >+ if (CCrystalHD::GetInstance()->DevicePresent()) >+ m_simpleConditions.insert("hascrystalhddevice"); >+#endif > #ifdef HAVE_LIBOPENMAX > m_simpleConditions.insert("have_libopenmax"); > #endif >--- kodi-15.1~/xbmc/system.h 2015-08-20 17:09:39.000000000 +0300 >+++ kodi-15.1/xbmc/system.h 2015-09-19 18:10:44.276612330 +0300 >@@ -106,6 +106,7 @@ > #define HAS_WIN32_NETWORK > #define HAS_IRSERVERSUITE > #define HAS_AUDIO >+#define HAVE_LIBCRYSTALHD 2 > #define HAS_WEB_SERVER > #define HAS_WEB_INTERFACE > #define HAVE_LIBSSH
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 30920
:
6267
|
6268
|
6274
|
6374
|
6376
|
6377
|
6382
|
6668