View | Details | Raw Unified | Return to bug 30920
Collapse All | Expand All

(-)kodi-15.1~/configure.ac (+52 lines)
Lines 200-205 vdpau_not_found="== Could not find libvd Link Here
200
vdpau_disabled="== VDPAU support manually disabled. =="
200
vdpau_disabled="== VDPAU support manually disabled. =="
201
vaapi_not_found="== Could not find libva. VAAPI support disabled. =="
201
vaapi_not_found="== Could not find libva. VAAPI support disabled. =="
202
vaapi_disabled="== VAAPI support manually disabled. =="
202
vaapi_disabled="== VAAPI support manually disabled. =="
203
crystalhd_not_found="== Could not find libcrystalhd. CrystalHD support disabled. =="
204
crystalhd_disabled="== CrystalHD support manually disabled. =="
203
vtbdecoder_enabled="== VTBDecoder support enabled. =="
205
vtbdecoder_enabled="== VTBDecoder support enabled. =="
204
vtbdecoder_disabled="== VTBDecoder support manually disabled. =="
206
vtbdecoder_disabled="== VTBDecoder support manually disabled. =="
205
openmax_disabled="== OpenMax support manually disabled. =="
207
openmax_disabled="== OpenMax support manually disabled. =="
Lines 286-291 AC_ARG_ENABLE([vaapi], Link Here
286
  [use_vaapi=$enableval],
288
  [use_vaapi=$enableval],
287
  [use_vaapi=auto])
289
  [use_vaapi=auto])
288
290
291
AC_ARG_ENABLE([crystalhd],
292
  [AS_HELP_STRING([--enable-crystalhd],
293
  [enable CrystalHD decoding (default is auto)])],
294
  [use_crystalhd=$enableval],
295
  [use_crystalhd=auto])
296
289
AC_ARG_ENABLE([vtbdecoder],
297
AC_ARG_ENABLE([vtbdecoder],
290
  [AS_HELP_STRING([--enable-vtbdecoder],
298
  [AS_HELP_STRING([--enable-vtbdecoder],
291
  [enable VTBDecoder decoding (default is auto)])],
299
  [enable VTBDecoder decoding (default is auto)])],
Lines 645-650 case $host in Link Here
645
     use_joystick=no
653
     use_joystick=no
646
     use_neon=yes
654
     use_neon=yes
647
     use_libcec=no
655
     use_libcec=no
656
     use_crystalhd=no
648
     use_vtbdecoder=yes
657
     use_vtbdecoder=yes
649
     use_optical_drive=no
658
     use_optical_drive=no
650
     use_dvdcss=no
659
     use_dvdcss=no
Lines 669-674 case $host in Link Here
669
     ;;
678
     ;;
670
  powerpc-apple-darwin*)
679
  powerpc-apple-darwin*)
671
     use_joystick=no
680
     use_joystick=no
681
     use_crystalhd=no
672
     use_vtbdecoder=no
682
     use_vtbdecoder=no
673
     ARCH="powerpc-osx"
683
     ARCH="powerpc-osx"
674
     use_arch="ppc"
684
     use_arch="ppc"
Lines 1881-1886 else Link Here
1881
  USE_VAAPI=0
1891
  USE_VAAPI=0
1882
fi
1892
fi
1883
1893
1894
# CrystalHD
1895
if test "x$use_crystalhd" != "xno"; then
1896
  SAVE_CFLAGS="$CFLAGS"
1897
  CFLAGS="-D__LINUX_USER__"
1898
  AC_CHECK_HEADER([libcrystalhd/libcrystalhd_if.h], [],
1899
    [ if test "x$use_crystalhd" = "xyes"; then
1900
        AC_MSG_ERROR($crystalhd_not_found)
1901
      else
1902
        use_crystalhd=no
1903
        AC_MSG_RESULT($crystalhd_not_found)
1904
      fi
1905
      USE_CRYSTALHD=0
1906
    ])
1907
    CFLAGS="$SAVE_CFLAGS"
1908
    if test "$host_vendor" != "apple"; then
1909
      XB_FIND_SONAME([CRYSTALHD], [crystalhd], [use_crystalhd])
1910
    fi
1911
    if test "x$use_crystalhd" != "xno"; then
1912
      SAVE_CFLAGS="$CFLAGS"
1913
      CFLAGS="-D__LINUX_USER__ -lcrystalhd"
1914
      # check for new crystalhd lib
1915
      AC_COMPILE_IFELSE(
1916
        [AC_LANG_SOURCE([#include <libcrystalhd/bc_dts_types.h>
1917
          #include <libcrystalhd/bc_dts_defs.h>
1918
          PBC_INFO_CRYSTAL bCrystalInfo;])],
1919
        [ AC_DEFINE([HAVE_LIBCRYSTALHD], [2], [Define to 2 if you have the 'New Broadcom Crystal HD' library.]) ], 
1920
        [ AC_DEFINE([HAVE_LIBCRYSTALHD], [1], [Define to 1 if you have the 'Old Broadcom Crystal HD' library.]) ])
1921
      CFLAGS="$SAVE_CFLAGS"
1922
      USE_CRYSTALHD=1
1923
    fi
1924
else
1925
  AC_MSG_NOTICE($crystalhd_disabled)
1926
  USE_CRYSTALHD=0
1927
fi
1928
1884
# VTBDecoder
1929
# VTBDecoder
1885
if test "x$use_vtbdecoder" != "xno"; then
1930
if test "x$use_vtbdecoder" != "xno"; then
1886
  if test "$host_vendor" = "apple" ; then
1931
  if test "$host_vendor" = "apple" ; then
Lines 2081-2086 else Link Here
2081
  final_message="$final_message\n  VAAPI:\tNo"
2126
  final_message="$final_message\n  VAAPI:\tNo"
2082
fi
2127
fi
2083
2128
2129
if test "x$use_crystalhd" != "xno"; then
2130
  final_message="$final_message\n  CrystalHD:\tYes"
2131
else
2132
  final_message="$final_message\n  CrystalHD:\tNo"
2133
fi
2134
2084
if test "x$use_vtbdecoder" != "xno"; then
2135
if test "x$use_vtbdecoder" != "xno"; then
2085
  final_message="$final_message\n  VTBDecoder:\tYes"
2136
  final_message="$final_message\n  VTBDecoder:\tYes"
2086
else
2137
else
Lines 2612-2617 AC_SUBST(USE_OPENGL) Link Here
2612
AC_SUBST(USE_OPENGLES)
2663
AC_SUBST(USE_OPENGLES)
2613
AC_SUBST(USE_VDPAU)
2664
AC_SUBST(USE_VDPAU)
2614
AC_SUBST(USE_VAAPI)
2665
AC_SUBST(USE_VAAPI)
2666
AC_SUBST(USE_CRYSTALHD)
2615
AC_SUBST(USE_LIBSMBCLIENT)
2667
AC_SUBST(USE_LIBSMBCLIENT)
2616
AC_SUBST(USE_LIBNFS)
2668
AC_SUBST(USE_LIBNFS)
2617
AC_SUBST(USE_AIRPLAY)
2669
AC_SUBST(USE_AIRPLAY)
(-)kodi-15.1~/system/settings/settings.xml (+9 lines)
Lines 786-791 Link Here
786
          <default>true</default>
786
          <default>true</default>
787
          <control type="toggle" />
787
          <control type="toggle" />
788
        </setting>
788
        </setting>
789
        <setting id="videoplayer.usechd" type="boolean" label="13428" help="36159">
790
          <requirement>HasCrystalHDDevice</requirement>
791
          <dependencies>
792
            <dependency type="enable" setting="videoplayer.decodingmethod" operator="is">1</dependency>
793
          </dependencies>
794
          <level>2</level>
795
          <default>true</default>
796
          <control type="toggle" />
797
        </setting>
789
        <setting id="videoplayer.useomxplayer" type="boolean" label="13458" help="13459">
798
        <setting id="videoplayer.useomxplayer" type="boolean" label="13458" help="13459">
790
          <requirement>HAS_OMXPLAYER</requirement>
799
          <requirement>HAS_OMXPLAYER</requirement>
791
          <level>2</level>
800
          <level>2</level>
(-)kodi-15.1~/tools/depends/target/libcrystalhd/Makefile (+15 lines)
Line 0 Link Here
1
include ../../Makefile.include
2
DEPS= ../../Makefile.include
3
4
SOURCE=libcrystalhd
5
6
all: .installed-$(PLATFORM)
7
8
.installed-$(PLATFORM): $(SOURCE)
9
	mkdir -p $(PREFIX)/include
10
	cp -rf $(SOURCE) $(PREFIX)/include/
11
	touch $@
12
13
clean:
14
distclean::
15
	rm -f .installed-$(PLATFORM)
(-)kodi-15.1~/tools/depends/target/Makefile (-2 / +2 lines)
Lines 27-38 endif Link Here
27
27
28
ifeq ($(OS),ios)
28
ifeq ($(OS),ios)
29
  DEPENDS += Backrow
29
  DEPENDS += Backrow
30
  EXCLUDED_DEPENDS = libcec libusb
30
  EXCLUDED_DEPENDS = libcec libusb libcrystalhd
31
endif
31
endif
32
32
33
ifeq ($(OS),osx)
33
ifeq ($(OS),osx)
34
  DEPENDS += libGLEW libsdl
34
  DEPENDS += libGLEW libsdl
35
  EXCLUDED_DEPENDS = libusb
35
  EXCLUDED_DEPENDS = libusb libcrystalhd
36
endif
36
endif
37
37
38
ifeq ($(OS),android)
38
ifeq ($(OS),android)
(-)kodi-15.1~/xbmc/Application.cpp (+11 lines)
Lines 130-135 Link Here
130
#ifdef HAS_JSONRPC
130
#ifdef HAS_JSONRPC
131
#include "interfaces/json-rpc/JSONRPC.h"
131
#include "interfaces/json-rpc/JSONRPC.h"
132
#endif
132
#endif
133
#if defined(HAVE_LIBCRYSTALHD)
134
#include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
135
#endif
133
#include "interfaces/AnnouncementManager.h"
136
#include "interfaces/AnnouncementManager.h"
134
#include "peripherals/Peripherals.h"
137
#include "peripherals/Peripherals.h"
135
#include "peripherals/dialogs/GUIDialogPeripheralManager.h"
138
#include "peripherals/dialogs/GUIDialogPeripheralManager.h"
Lines 1215-1220 bool CApplication::Initialize() Link Here
1215
1218
1216
  m_slowTimer.StartZero();
1219
  m_slowTimer.StartZero();
1217
1220
1221
#if defined(HAVE_LIBCRYSTALHD)
1222
  CCrystalHD::GetInstance();
1223
#endif
1224
1218
  CAddonMgr::Get().StartServices(true);
1225
  CAddonMgr::Get().StartServices(true);
1219
1226
1220
  // configure seek handler
1227
  // configure seek handler
Lines 2665-2670 void CApplication::Stop(int exitCode) Link Here
2665
      XBMCHelper::GetInstance().Stop();
2672
      XBMCHelper::GetInstance().Stop();
2666
#endif
2673
#endif
2667
2674
2675
#if defined(HAVE_LIBCRYSTALHD)
2676
    CCrystalHD::RemoveInstance();
2677
#endif
2678
2668
    g_mediaManager.Stop();
2679
    g_mediaManager.Stop();
2669
2680
2670
    // Stop services before unloading Python
2681
    // Stop services before unloading Python
(-)kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/DVDFactoryCodec.cpp (+32 lines)
Lines 42-47 Link Here
42
#endif
42
#endif
43
#include "Video/MMALCodec.h"
43
#include "Video/MMALCodec.h"
44
#include "Video/DVDVideoCodecStageFright.h"
44
#include "Video/DVDVideoCodecStageFright.h"
45
#if defined(HAVE_LIBCRYSTALHD)
46
#include "Video/DVDVideoCodecCrystalHD.h"
47
#endif
45
#if defined(HAS_LIBAMCODEC)
48
#if defined(HAS_LIBAMCODEC)
46
#include "utils/AMLUtils.h"
49
#include "utils/AMLUtils.h"
47
#include "Video/DVDVideoCodecAmlogic.h"
50
#include "Video/DVDVideoCodecAmlogic.h"
Lines 154-159 CDVDVideoCodec* CDVDFactoryCodec::Create Link Here
154
#elif defined(TARGET_DARWIN)
157
#elif defined(TARGET_DARWIN)
155
  hwSupport += "VideoToolBoxDecoder:no ";
158
  hwSupport += "VideoToolBoxDecoder:no ";
156
#endif
159
#endif
160
#ifdef HAVE_LIBCRYSTALHD
161
  hwSupport += "CrystalHD:yes ";
162
#else
163
  hwSupport += "CrystalHD:no ";
164
#endif
157
#if defined(HAS_LIBAMCODEC)
165
#if defined(HAS_LIBAMCODEC)
158
  hwSupport += "AMCodec:yes ";
166
  hwSupport += "AMCodec:yes ";
159
#else
167
#else
Lines 260-265 CDVDVideoCodec* CDVDFactoryCodec::Create Link Here
260
      }
268
      }
261
    }
269
    }
262
  }
270
  }
271
#endif
272
273
#if defined(HAVE_LIBCRYSTALHD)
274
  if (!hint.software && CSettings::Get().GetBool("videoplayer.usechd"))
275
  {
276
    if (CCrystalHD::GetInstance()->DevicePresent())
277
    {
278
      switch(hint.codec)
279
      {
280
        case AV_CODEC_ID_VC1:
281
        case AV_CODEC_ID_WMV3:
282
        case AV_CODEC_ID_H264:
283
        case AV_CODEC_ID_MPEG2VIDEO:
284
          if (hint.codec == AV_CODEC_ID_H264 && hint.ptsinvalid)
285
            break;
286
          if (hint.codec == AV_CODEC_ID_MPEG2VIDEO && hint.width <= 720)
287
            break;
288
          if ( (pCodec = OpenCodec(new CDVDVideoCodecCrystalHD(), hint, options)) ) return pCodec;
289
        break;
290
        default:
291
        break;
292
      }
293
    }
294
  }
263
#endif
295
#endif
264
296
265
#if defined(TARGET_ANDROID)
297
#if defined(TARGET_ANDROID)
(-)kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp (+2010 lines)
Line 0 Link Here
1
/*
2
 *      Copyright (C) 2005-2013 Team XBMC
3
 *      http://xbmc.org
4
 *
5
 *  This Program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2, or (at your option)
8
 *  any later version.
9
 *
10
 *  This Program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with XBMC; see the file COPYING.  If not, see
17
 *  <http://www.gnu.org/licenses/>.
18
 *
19
 */
20
21
#include "system.h"
22
#if defined(TARGET_WINDOWS)
23
#include "WIN32Util.h"
24
#include "util.h"
25
#include "dialogs/GUIDialogKaiToast.h"
26
#include "guilib/LocalizeStrings.h"
27
#endif
28
29
#if defined(HAVE_LIBCRYSTALHD)
30
#include "CrystalHD.h"
31
32
#include "DVDClock.h"
33
#include "DynamicDll.h"
34
#include "utils/SystemInfo.h"
35
#include "threads/Atomics.h"
36
#include "threads/Thread.h"
37
#include "utils/log.h"
38
extern "C" {
39
#include "libswscale/swscale.h"
40
}
41
#include "utils/TimeUtils.h"
42
#include "windowing/WindowingFactory.h"
43
#include "cores/FFmpeg.h"
44
45
namespace BCM
46
{
47
  #if defined(TARGET_WINDOWS)
48
    typedef void		*HANDLE;
49
  #else
50
    #ifndef __LINUX_USER__
51
      #define __LINUX_USER__
52
    #endif
53
  #endif
54
55
  #include <libcrystalhd/bc_dts_types.h>
56
  #include <libcrystalhd/bc_dts_defs.h>
57
  #include <libcrystalhd/libcrystalhd_if.h>
58
};
59
60
#define __MODULE_NAME__ "CrystalHD"
61
//#define USE_CHD_SINGLE_THREADED_API
62
class DllLibCrystalHDInterface
63
{
64
public:
65
  virtual ~DllLibCrystalHDInterface() {}
66
  virtual BCM::BC_STATUS DtsDeviceOpen(void *hDevice, uint32_t mode)=0;
67
  virtual BCM::BC_STATUS DtsDeviceClose(void *hDevice)=0;
68
  virtual BCM::BC_STATUS DtsOpenDecoder(void *hDevice, uint32_t StreamType)=0;
69
  virtual BCM::BC_STATUS DtsCloseDecoder(void *hDevice)=0;
70
  virtual BCM::BC_STATUS DtsStartDecoder(void *hDevice)=0;
71
  virtual BCM::BC_STATUS DtsSetVideoParams(void *hDevice, uint32_t videoAlg, int FGTEnable, int MetaDataEnable, int Progressive, uint32_t OptFlags)=0;
72
  virtual BCM::BC_STATUS DtsStartCapture(void *hDevice)=0;
73
  virtual BCM::BC_STATUS DtsFlushRxCapture(void *hDevice, int bDiscardOnly)=0;
74
  virtual BCM::BC_STATUS DtsSetFFRate(void *hDevice, uint32_t rate)=0;
75
  virtual BCM::BC_STATUS DtsGetDriverStatus(void *hDevice, BCM::BC_DTS_STATUS *pStatus)=0;
76
  virtual BCM::BC_STATUS DtsProcInput(void *hDevice, uint8_t *pUserData, uint32_t ulSizeInBytes, uint64_t timeStamp, int encrypted)=0;
77
  virtual BCM::BC_STATUS DtsProcOutput(void *hDevice, uint32_t milliSecWait, BCM::BC_DTS_PROC_OUT *pOut)=0;
78
  virtual BCM::BC_STATUS DtsProcOutputNoCopy(void *hDevice, uint32_t milliSecWait, BCM::BC_DTS_PROC_OUT *pOut)=0;
79
  virtual BCM::BC_STATUS DtsReleaseOutputBuffs(void *hDevice, void *Reserved, int fChange)=0;
80
  virtual BCM::BC_STATUS DtsSetSkipPictureMode(void *hDevice, uint32_t Mode)=0;
81
  virtual BCM::BC_STATUS DtsFlushInput(void *hDevice, uint32_t SkipMode)=0;
82
83
#if (HAVE_LIBCRYSTALHD == 2)
84
  // new function calls, only present in new driver/library so manually load them
85
  virtual BCM::BC_STATUS DtsGetVersion(void *hDevice, uint32_t *DrVer, uint32_t *DilVer)=0;
86
  virtual BCM::BC_STATUS DtsSetInputFormat(void *hDevice, BCM::BC_INPUT_FORMAT *pInputFormat)=0;
87
  virtual BCM::BC_STATUS DtsGetColorPrimaries(void *hDevice, uint32_t *colorPrimaries)=0;
88
  virtual BCM::BC_STATUS DtsSetColorSpace(void *hDevice, BCM::BC_OUTPUT_FORMAT Mode422)=0;
89
  virtual BCM::BC_STATUS DtsGetCapabilities(void *hDevice, BCM::BC_HW_CAPS *CapsBuffer)=0;
90
  virtual BCM::BC_STATUS DtsSetScaleParams(void *hDevice, BCM::BC_SCALING_PARAMS *ScaleParams)=0;
91
  virtual BCM::BC_STATUS DtsIsEndOfStream(void *hDevice, uint8_t* bEOS)=0;
92
  virtual BCM::BC_STATUS DtsCrystalHDVersion(void *hDevice, BCM::BC_INFO_CRYSTAL *CrystalInfo)=0;
93
#endif
94
};
95
96
class DllLibCrystalHD : public DllDynamic, DllLibCrystalHDInterface
97
{
98
  DECLARE_DLL_WRAPPER(DllLibCrystalHD, DLL_PATH_LIBCRYSTALHD)
99
100
  DEFINE_METHOD2(BCM::BC_STATUS, DtsDeviceOpen,      (void *p1, uint32_t p2))
101
  DEFINE_METHOD1(BCM::BC_STATUS, DtsDeviceClose,     (void *p1))
102
  DEFINE_METHOD2(BCM::BC_STATUS, DtsOpenDecoder,     (void *p1, uint32_t p2))
103
  DEFINE_METHOD1(BCM::BC_STATUS, DtsCloseDecoder,    (void *p1))
104
  DEFINE_METHOD1(BCM::BC_STATUS, DtsStartDecoder,    (void *p1))
105
  DEFINE_METHOD1(BCM::BC_STATUS, DtsStopDecoder,     (void *p1))
106
  DEFINE_METHOD6(BCM::BC_STATUS, DtsSetVideoParams,  (void *p1, uint32_t p2, int p3, int p4, int p5, uint32_t p6))
107
  DEFINE_METHOD1(BCM::BC_STATUS, DtsStartCapture,    (void *p1))
108
  DEFINE_METHOD2(BCM::BC_STATUS, DtsFlushRxCapture,  (void *p1, int p2))
109
  DEFINE_METHOD2(BCM::BC_STATUS, DtsSetFFRate,       (void *p1, uint32_t p2))
110
  DEFINE_METHOD2(BCM::BC_STATUS, DtsGetDriverStatus, (void *p1, BCM::BC_DTS_STATUS *p2))
111
  DEFINE_METHOD5(BCM::BC_STATUS, DtsProcInput,       (void *p1, uint8_t *p2, uint32_t p3, uint64_t p4, int p5))
112
  DEFINE_METHOD3(BCM::BC_STATUS, DtsProcOutput,      (void *p1, uint32_t p2, BCM::BC_DTS_PROC_OUT *p3))
113
  DEFINE_METHOD3(BCM::BC_STATUS, DtsProcOutputNoCopy,(void *p1, uint32_t p2, BCM::BC_DTS_PROC_OUT *p3))
114
  DEFINE_METHOD3(BCM::BC_STATUS, DtsReleaseOutputBuffs,(void *p1, void *p2, int p3))
115
  DEFINE_METHOD2(BCM::BC_STATUS, DtsSetSkipPictureMode,(void *p1, uint32_t p2))
116
  DEFINE_METHOD2(BCM::BC_STATUS, DtsFlushInput,      (void *p1, uint32_t p2))
117
118
#if (HAVE_LIBCRYSTALHD == 2)
119
  DEFINE_METHOD3(BCM::BC_STATUS, DtsGetVersion,      (void *p1, uint32_t *p2, uint32_t *p3))
120
  DEFINE_METHOD2(BCM::BC_STATUS, DtsSetInputFormat,  (void *p1, BCM::BC_INPUT_FORMAT *p2))
121
  DEFINE_METHOD2(BCM::BC_STATUS, DtsGetColorPrimaries,(void *p1, uint32_t *p2))
122
  DEFINE_METHOD2(BCM::BC_STATUS, DtsSetColorSpace,   (void *p1, BCM::BC_OUTPUT_FORMAT p2))
123
  DEFINE_METHOD2(BCM::BC_STATUS, DtsGetCapabilities, (void *p1, BCM::BC_HW_CAPS *p2))
124
  DEFINE_METHOD2(BCM::BC_STATUS, DtsSetScaleParams,  (void *p1, BCM::BC_SCALING_PARAMS *p2))
125
  DEFINE_METHOD2(BCM::BC_STATUS, DtsIsEndOfStream,   (void *p1, uint8_t *p2))
126
  DEFINE_METHOD2(BCM::BC_STATUS, DtsCrystalHDVersion,(void *p1, BCM::BC_INFO_CRYSTAL *p2))
127
#endif
128
129
  BEGIN_METHOD_RESOLVE()
130
    RESOLVE_METHOD_RENAME(DtsDeviceOpen,      DtsDeviceOpen)
131
    RESOLVE_METHOD_RENAME(DtsDeviceClose,     DtsDeviceClose)
132
    RESOLVE_METHOD_RENAME(DtsOpenDecoder,     DtsOpenDecoder)
133
    RESOLVE_METHOD_RENAME(DtsCloseDecoder,    DtsCloseDecoder)
134
    RESOLVE_METHOD_RENAME(DtsStartDecoder,    DtsStartDecoder)
135
    RESOLVE_METHOD_RENAME(DtsStopDecoder,     DtsStopDecoder)
136
    RESOLVE_METHOD_RENAME(DtsSetVideoParams,  DtsSetVideoParams)
137
    RESOLVE_METHOD_RENAME(DtsStartCapture,    DtsStartCapture)
138
    RESOLVE_METHOD_RENAME(DtsFlushRxCapture,  DtsFlushRxCapture)
139
    RESOLVE_METHOD_RENAME(DtsSetFFRate,       DtsSetFFRate)
140
    RESOLVE_METHOD_RENAME(DtsGetDriverStatus, DtsGetDriverStatus)
141
    RESOLVE_METHOD_RENAME(DtsProcInput,       DtsProcInput)
142
    RESOLVE_METHOD_RENAME(DtsProcOutput,      DtsProcOutput)
143
    RESOLVE_METHOD_RENAME(DtsProcOutputNoCopy,DtsProcOutputNoCopy)
144
    RESOLVE_METHOD_RENAME(DtsReleaseOutputBuffs,DtsReleaseOutputBuffs)
145
    RESOLVE_METHOD_RENAME(DtsSetSkipPictureMode,DtsSetSkipPictureMode)
146
    RESOLVE_METHOD_RENAME(DtsFlushInput,      DtsFlushInput)
147
  END_METHOD_RESOLVE()
148
  
149
public:
150
  bool LoadNewLibFunctions(void)
151
  {
152
#if (HAVE_LIBCRYSTALHD == 2)
153
    int rtn;
154
    rtn  = m_dll->ResolveExport("DtsGetVersion",       (void**)&m_DtsGetVersion_ptr, false);
155
    rtn &= m_dll->ResolveExport("DtsSetInputFormat",   (void**)&m_DtsSetInputFormat_ptr, false);
156
    rtn &= m_dll->ResolveExport("DtsGetColorPrimaries",(void**)&m_DtsGetColorPrimaries_ptr, false);
157
    rtn &= m_dll->ResolveExport("DtsSetColorSpace",    (void**)&m_DtsSetColorSpace_ptr, false);
158
    rtn &= m_dll->ResolveExport("DtsGetCapabilities",  (void**)&m_DtsGetCapabilities_ptr, false);
159
    rtn &= m_dll->ResolveExport("DtsSetScaleParams",   (void**)&m_DtsSetScaleParams_ptr, false);
160
    rtn &= m_dll->ResolveExport("DtsIsEndOfStream",    (void**)&m_DtsIsEndOfStream_ptr, false);
161
    rtn &= m_dll->ResolveExport("DtsCrystalHDVersion", (void**)&m_DtsCrystalHDVersion_ptr, false);
162
    rtn &= m_dll->ResolveExport("DtsSetInputFormat",   (void**)&m_DtsSetInputFormat_ptr, false);
163
    return(rtn == 1);
164
#else
165
    return false;
166
#endif
167
  };
168
};
169
170
void PrintFormat(BCM::BC_PIC_INFO_BLOCK &pib);
171
void BcmDebugLog( BCM::BC_STATUS lResult, std::string strFuncName="");
172
173
const char* g_DtsStatusText[] = {
174
	"BC_STS_SUCCESS",
175
	"BC_STS_INV_ARG",
176
	"BC_STS_BUSY",		
177
	"BC_STS_NOT_IMPL",		
178
	"BC_STS_PGM_QUIT",		
179
	"BC_STS_NO_ACCESS",	
180
	"BC_STS_INSUFF_RES",	
181
	"BC_STS_IO_ERROR",		
182
	"BC_STS_NO_DATA",		
183
	"BC_STS_VER_MISMATCH",
184
	"BC_STS_TIMEOUT",		
185
	"BC_STS_FW_CMD_ERR",	
186
	"BC_STS_DEC_NOT_OPEN",
187
	"BC_STS_ERR_USAGE",
188
	"BC_STS_IO_USER_ABORT",
189
	"BC_STS_IO_XFR_ERROR",
190
	"BC_STS_DEC_NOT_STARTED",
191
	"BC_STS_FWHEX_NOT_FOUND",
192
	"BC_STS_FMT_CHANGE",
193
	"BC_STS_HIF_ACCESS",
194
	"BC_STS_CMD_CANCELLED",
195
	"BC_STS_FW_AUTH_FAILED",
196
	"BC_STS_BOOTLOADER_FAILED",
197
	"BC_STS_CERT_VERIFY_ERROR",
198
	"BC_STS_DEC_EXIST_OPEN",
199
	"BC_STS_PENDING",
200
	"BC_STS_CLK_NOCHG"
201
};
202
203
////////////////////////////////////////////////////////////////////////////////////////////
204
class CMPCOutputThread : public CThread
205
{
206
public:
207
  CMPCOutputThread(void *device, DllLibCrystalHD *dll, bool has_bcm70015);
208
  virtual ~CMPCOutputThread();
209
210
  unsigned int        GetReadyCount(void);
211
  unsigned int        GetFreeCount(void);
212
  CPictureBuffer*     ReadyListPop(void);
213
  void                FreeListPush(CPictureBuffer* pBuffer);
214
  bool                WaitOutput(unsigned int msec);
215
216
protected:
217
  void                DoFrameRateTracking(double timestamp);
218
  void                SetFrameRate(uint32_t resolution);
219
  void                SetAspectRatio(BCM::BC_PIC_INFO_BLOCK *pic_info);
220
  void                CopyOutAsNV12(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride);
221
  void                CopyOutAsNV12DeInterlace(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride);
222
  void                CopyOutAsYV12(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride);
223
  void                CopyOutAsYV12DeInterlace(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride);
224
  void                CheckUpperLeftGreenPixelHack(CPictureBuffer *pBuffer);
225
  bool                GetDecoderOutput(void);
226
  virtual void        Process(void);
227
228
  CSyncPtrQueue<CPictureBuffer> m_FreeList;
229
  CSyncPtrQueue<CPictureBuffer> m_ReadyList;
230
231
  DllLibCrystalHD     *m_dll;
232
  void                *m_device;
233
  bool                m_has_bcm70015;
234
  unsigned int        m_timeout;
235
  bool                m_format_valid;
236
  bool                m_is_live_stream;
237
  int                 m_width;
238
  int                 m_height;
239
  uint64_t            m_timestamp;
240
  bool                m_output_YV12;
241
  uint64_t            m_PictureNumber;
242
  uint8_t             m_color_space;
243
  unsigned int        m_color_range;
244
  unsigned int        m_color_matrix;
245
  int                 m_interlace;
246
  bool                m_framerate_tracking;
247
  uint64_t            m_framerate_cnt;
248
  double              m_framerate_timestamp;
249
  double              m_framerate;
250
  int                 m_aspectratio_x;
251
  int                 m_aspectratio_y;
252
  CEvent              m_ready_event;
253
  struct SwsContext   *m_sw_scale_ctx;
254
};
255
256
////////////////////////////////////////////////////////////////////////////////////////////
257
#if defined(TARGET_DARWIN)
258
#pragma mark -
259
#endif
260
CPictureBuffer::CPictureBuffer(ERenderFormat format, int width, int height)
261
{
262
  m_width = width;
263
  m_height = height;
264
  m_field = CRYSTALHD_FIELD_FULL;
265
  m_interlace = false;
266
  m_timestamp = DVD_NOPTS_VALUE;
267
  m_PictureNumber = 0;
268
  m_color_space = BCM::MODE420;
269
  m_color_range = 0;
270
  m_color_matrix = 4;
271
  m_format = format;
272
  m_framerate = 0;
273
  
274
  switch(m_format)
275
  {
276
    default:
277
    case RENDER_FMT_NV12:
278
      // setup y plane
279
      m_y_buffer_size = m_width * m_height;
280
      m_y_buffer_ptr = (unsigned char*)_aligned_malloc(m_y_buffer_size, 16);
281
  
282
      m_u_buffer_size = 0;
283
      m_v_buffer_size = 0;
284
      m_u_buffer_ptr = NULL;
285
      m_v_buffer_ptr = NULL;
286
      m_uv_buffer_size = m_y_buffer_size / 2;
287
      m_uv_buffer_ptr = (unsigned char*)_aligned_malloc(m_uv_buffer_size, 16);
288
    break;
289
    case RENDER_FMT_YUYV422:
290
      // setup y plane
291
      m_y_buffer_size = (2 * m_width) * m_height;
292
      m_y_buffer_ptr = (unsigned char*)_aligned_malloc(m_y_buffer_size, 16);
293
  
294
      m_uv_buffer_size = 0;
295
      m_uv_buffer_ptr = NULL;
296
      m_u_buffer_size = 0;
297
      m_v_buffer_size = 0;
298
      m_u_buffer_ptr = NULL;
299
      m_v_buffer_ptr = NULL;
300
    break;
301
    case RENDER_FMT_YUV420P:
302
      // setup y plane
303
      m_y_buffer_size = m_width * m_height;
304
      m_y_buffer_ptr = (unsigned char*)_aligned_malloc(m_y_buffer_size, 16);
305
  
306
      m_uv_buffer_size = 0;
307
      m_uv_buffer_ptr = NULL;
308
      m_u_buffer_size = m_y_buffer_size / 4;
309
      m_v_buffer_size = m_y_buffer_size / 4;
310
      m_u_buffer_ptr = (unsigned char*)_aligned_malloc(m_u_buffer_size, 16);
311
      m_v_buffer_ptr = (unsigned char*)_aligned_malloc(m_v_buffer_size, 16);
312
    break;
313
  }
314
}
315
316
CPictureBuffer::~CPictureBuffer()
317
{
318
  if (m_y_buffer_ptr) _aligned_free(m_y_buffer_ptr);
319
  if (m_u_buffer_ptr) _aligned_free(m_u_buffer_ptr);
320
  if (m_v_buffer_ptr) _aligned_free(m_v_buffer_ptr);
321
  if (m_uv_buffer_ptr) _aligned_free(m_uv_buffer_ptr);
322
}
323
324
/////////////////////////////////////////////////////////////////////////////////////////////
325
#if defined(TARGET_DARWIN)
326
#pragma mark -
327
#endif
328
CMPCOutputThread::CMPCOutputThread(void *device, DllLibCrystalHD *dll, bool has_bcm70015) :
329
  CThread("MPCOutput"),
330
  m_dll(dll),
331
  m_device(device),
332
  m_has_bcm70015(has_bcm70015),
333
  m_timeout(20),
334
  m_format_valid(false),
335
  m_is_live_stream(false),
336
  m_width(0),
337
  m_height(0),
338
  m_timestamp(0),
339
  m_PictureNumber(0),
340
  m_color_space(0),
341
  m_color_range(0),
342
  m_color_matrix(0),
343
  m_interlace(0),
344
  m_framerate_tracking(false),
345
  m_framerate_cnt(0),
346
  m_framerate_timestamp(0.0),
347
  m_framerate(0.0),
348
  m_aspectratio_x(1),
349
  m_aspectratio_y(1)
350
{
351
  m_sw_scale_ctx = NULL;
352
  
353
  if (g_Windowing.GetRenderQuirks() & RENDER_QUIRKS_YV12_PREFERED)
354
    m_output_YV12 = true;
355
  else
356
    m_output_YV12 = false;
357
}
358
359
CMPCOutputThread::~CMPCOutputThread()
360
{
361
  while(m_ReadyList.Count())
362
    delete m_ReadyList.Pop();
363
  while(m_FreeList.Count())
364
    delete m_FreeList.Pop();
365
    
366
  if (m_sw_scale_ctx)
367
    sws_freeContext(m_sw_scale_ctx);
368
}
369
370
unsigned int CMPCOutputThread::GetReadyCount(void)
371
{
372
  return m_ReadyList.Count();
373
}
374
375
unsigned int CMPCOutputThread::GetFreeCount(void)
376
{
377
  return m_FreeList.Count();
378
}
379
380
CPictureBuffer* CMPCOutputThread::ReadyListPop(void)
381
{
382
  CPictureBuffer *pBuffer = m_ReadyList.Pop();
383
  return pBuffer;
384
}
385
386
void CMPCOutputThread::FreeListPush(CPictureBuffer* pBuffer)
387
{
388
  m_FreeList.Push(pBuffer);
389
}
390
391
bool CMPCOutputThread::WaitOutput(unsigned int msec)
392
{
393
  return m_ready_event.WaitMSec(msec);
394
}
395
396
void CMPCOutputThread::DoFrameRateTracking(double timestamp)
397
{
398
  if (timestamp != DVD_NOPTS_VALUE)
399
  {
400
    double duration;
401
    // if timestamp does not start at a low value we 
402
    // came in the middle of an online live stream
403
    // 250 ms is a fourth of a 25fps source
404
    // if timestamp is larger than that at the beginning
405
    // we are much more out of sync than with the rough 
406
    // calculation. To cover these 250 ms we need
407
    // roughly 5 seconds of video stream to get back
408
    // in sync
409
    if (m_framerate_cnt == 0 && timestamp > 250000.0)
410
      m_is_live_stream = true;
411
    
412
    duration = timestamp - m_framerate_timestamp;
413
    if (duration > 0.0)
414
    {
415
      double framerate;
416
      // cnt count has to be done here, cause we miss frames
417
      // if framerate will not calculated correctly and
418
      // duration has to be > 0.0 so we do not calc images twice
419
      m_framerate_cnt++;
420
421
      m_framerate_timestamp += duration;
422
      framerate = DVD_TIME_BASE / duration;
423
      // qualify framerate, we don't care about absolute value, just
424
      // want to to verify range. Timestamp could be borked so ignore
425
      // anything that does not verify.
426
      // 60, 59.94 -> 60
427
      // 50, 49.95 -> 50
428
      // 30, 29.97 -> 30
429
      // 25, 24.975 -> 25
430
      // 24, 23.976 -> 24
431
      switch ((int)(0.5 + framerate))
432
      {
433
        case 60:
434
        case 50:
435
        case 30:
436
        case 25:
437
        case 24:
438
          // if we have such a live stream framerate is more exact than calculating
439
          // cause of m_framerate_cnt and timestamp do not match in any way
440
          m_framerate = m_is_live_stream ? framerate : DVD_TIME_BASE / (m_framerate_timestamp/m_framerate_cnt);
441
        break;
442
      }
443
    }
444
  }
445
}
446
447
void CMPCOutputThread::SetFrameRate(uint32_t resolution)
448
{
449
  m_interlace = FALSE;
450
451
  switch (resolution)
452
  {
453
    case BCM::vdecRESOLUTION_1080p30:
454
      m_framerate = 30.0;
455
    break;
456
    case BCM::vdecRESOLUTION_1080p29_97:
457
      m_framerate = 30.0 * 1000.0 / 1001.0;
458
    break;
459
    case BCM::vdecRESOLUTION_1080p25 :
460
      m_framerate = 25.0;
461
    break;
462
    case BCM::vdecRESOLUTION_1080p24:
463
      m_framerate = 24.0;
464
    break;
465
    case BCM::vdecRESOLUTION_1080p23_976:
466
      m_framerate = 24.0 * 1000.0 / 1001.0;
467
    break;
468
    case BCM::vdecRESOLUTION_1080p0:
469
      // 1080p0 is ambiguious, could be 23.976 or 29.97 fps, decoder
470
      // just does not know. 1080p@23_976 is more common but this
471
      // will mess up 1080p@29_97 playback. We really need to verify
472
      // which framerate with duration tracking.
473
      m_framerate_tracking = true;
474
      m_framerate = 24.0 * 1000.0 / 1001.0;
475
    break;
476
    
477
    case BCM::vdecRESOLUTION_1080i29_97:
478
      m_framerate = 30.0 * 1000.0 / 1001.0;
479
      m_interlace = TRUE;
480
    break;
481
    case BCM::vdecRESOLUTION_1080i0:
482
      m_framerate = 30.0 * 1000.0 / 1001.0;
483
      m_interlace = TRUE;
484
    break;
485
    case BCM::vdecRESOLUTION_1080i:
486
      m_framerate = 30.0 * 1000.0 / 1001.0;
487
      m_interlace = TRUE;
488
    break;
489
    case BCM::vdecRESOLUTION_1080i25:
490
      m_framerate = 25.0 * 1000.0 / 1001.0;
491
      m_interlace = TRUE;
492
    break;
493
    
494
    case BCM::vdecRESOLUTION_720p59_94:
495
      m_framerate = 60.0 * 1000.0 / 1001.0;
496
    break;
497
    case BCM::vdecRESOLUTION_720p:
498
      m_framerate = 60.0 * 1000.0 / 1001.0;
499
    break;
500
    case BCM::vdecRESOLUTION_720p50:
501
      m_framerate = 50.0 * 1000.0 / 1001.0;
502
    break;
503
    case BCM::vdecRESOLUTION_720p29_97:
504
      m_framerate = 30.0 * 1000.0 / 1001.0;
505
    break;
506
    case BCM::vdecRESOLUTION_720p24:
507
      m_framerate = 24.0;
508
    break;
509
    case BCM::vdecRESOLUTION_720p23_976:
510
      // some 720p/25 will be identifed as this, enable tracking.
511
      m_framerate_tracking = true;
512
      m_framerate = 24.0 * 1000.0 / 1001.0;
513
    break;
514
    case BCM::vdecRESOLUTION_720p0:
515
      // 720p0 is ambiguious, could be 23.976, 29.97 or 59.97 fps, decoder
516
      // just does not know. 720p@23_976 is more common but this
517
      // will mess up other playback. We really need to verify
518
      // which framerate with duration tracking.
519
      m_framerate_tracking = true;
520
      m_framerate = 24.0 * 1000.0 / 1001.0;
521
    break;
522
    
523
    case BCM::vdecRESOLUTION_576p25:
524
      m_framerate = 25.0;
525
    break;
526
    case BCM::vdecRESOLUTION_576p0:
527
      m_framerate = 25.0;
528
    break;
529
    case BCM::vdecRESOLUTION_PAL1:
530
      m_framerate = 25.0 * 1000.0 / 1001.0;
531
      m_interlace = TRUE;
532
    break;
533
    
534
    case BCM::vdecRESOLUTION_480p0:
535
      m_framerate = 60.0;
536
    break;
537
    case BCM::vdecRESOLUTION_480p:
538
      m_framerate = 60.0 * 1000.0 / 1001.0;
539
    break;
540
    case BCM::vdecRESOLUTION_480p29_97:
541
      m_framerate = 30.0 * 1000.0 / 1001.0;
542
    break;
543
    case BCM::vdecRESOLUTION_480p23_976:
544
      m_framerate = 24.0 * 1000.0 / 1001.0;
545
    break;
546
    
547
    case BCM::vdecRESOLUTION_480i0:
548
      m_framerate = 30.0 * 1000.0 / 1001.0;
549
      m_interlace = TRUE;
550
    break;
551
    case BCM::vdecRESOLUTION_480i:
552
      m_framerate = 30.0 * 1000.0 / 1001.0;
553
      m_interlace = TRUE;
554
    break;
555
    case BCM::vdecRESOLUTION_NTSC:
556
      m_framerate = 30.0 * 1000.0 / 1001.0;
557
      m_interlace = TRUE;
558
    break;
559
    
560
    default:
561
      m_framerate_tracking = true;
562
      m_framerate = 24.0 * 1000.0 / 1001.0;
563
    break;
564
  }
565
566
  CLog::Log(LOGDEBUG, "%s: resolution = %x  interlace = %d", __MODULE_NAME__, resolution, m_interlace);
567
}
568
569
void CMPCOutputThread::SetAspectRatio(BCM::BC_PIC_INFO_BLOCK *pic_info)
570
{
571
	switch(pic_info->aspect_ratio)
572
  {
573
    case BCM::vdecAspectRatioSquare:
574
      m_aspectratio_x = 1;
575
      m_aspectratio_y = 1;
576
    break;
577
    case BCM::vdecAspectRatio12_11:
578
      m_aspectratio_x = 12;
579
      m_aspectratio_y = 11;
580
    break;
581
    case BCM::vdecAspectRatio10_11:
582
      m_aspectratio_x = 10;
583
      m_aspectratio_y = 11;
584
    break;
585
    case BCM::vdecAspectRatio16_11:
586
      m_aspectratio_x = 16;
587
      m_aspectratio_y = 11;
588
    break;
589
    case BCM::vdecAspectRatio40_33:
590
      m_aspectratio_x = 40;
591
      m_aspectratio_y = 33;
592
    break;
593
    case BCM::vdecAspectRatio24_11:
594
      m_aspectratio_x = 24;
595
      m_aspectratio_y = 11;
596
    break;
597
    case BCM::vdecAspectRatio20_11:
598
      m_aspectratio_x = 20;
599
      m_aspectratio_y = 11;
600
    break;
601
    case BCM::vdecAspectRatio32_11:
602
      m_aspectratio_x = 32;
603
      m_aspectratio_y = 11;
604
    break;
605
    case BCM::vdecAspectRatio80_33:
606
      m_aspectratio_x = 80;
607
      m_aspectratio_y = 33;
608
    break;
609
    case BCM::vdecAspectRatio18_11:
610
      m_aspectratio_x = 18;
611
      m_aspectratio_y = 11;
612
    break;
613
    case BCM::vdecAspectRatio15_11:
614
      m_aspectratio_x = 15;
615
      m_aspectratio_y = 11;
616
    break;
617
    case BCM::vdecAspectRatio64_33:
618
      m_aspectratio_x = 64;
619
      m_aspectratio_y = 33;
620
    break;
621
    case BCM::vdecAspectRatio160_99:
622
      m_aspectratio_x = 160;
623
      m_aspectratio_y = 99;
624
    break;
625
    case BCM::vdecAspectRatio4_3:
626
      m_aspectratio_x = 4;
627
      m_aspectratio_y = 3;
628
    break;
629
    case BCM::vdecAspectRatio16_9:
630
      m_aspectratio_x = 16;
631
      m_aspectratio_y = 9;
632
    break;
633
    case BCM::vdecAspectRatio221_1:
634
      m_aspectratio_x = 221;
635
      m_aspectratio_y = 1;
636
    break;
637
    case BCM::vdecAspectRatioUnknown:
638
      m_aspectratio_x = 0;
639
      m_aspectratio_y = 0;
640
    break;
641
642
    case BCM::vdecAspectRatioOther:
643
      m_aspectratio_x = pic_info->custom_aspect_ratio_width_height & 0x0000ffff;
644
      m_aspectratio_y = pic_info->custom_aspect_ratio_width_height >> 16;
645
    break;
646
  }
647
  if(m_aspectratio_x == 0)
648
  {
649
    m_aspectratio_x = 1;
650
    m_aspectratio_y = 1;
651
  }
652
653
  CLog::Log(LOGDEBUG, "%s: dec_par x = %d, dec_par y = %d", __MODULE_NAME__, m_aspectratio_x, m_aspectratio_y);
654
}
655
656
void CMPCOutputThread::CopyOutAsYV12(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride)
657
{
658
  // copy y
659
  if (w == stride)
660
  {
661
    memcpy(pBuffer->m_y_buffer_ptr, procOut->Ybuff, w * h);
662
  }
663
  else
664
  {
665
    uint8_t *s_y = procOut->Ybuff;
666
    uint8_t *d_y = pBuffer->m_y_buffer_ptr;
667
    for (int y = 0; y < h; y++, s_y += stride, d_y += w)
668
      memcpy(d_y, s_y, w);
669
  }
670
  //copy chroma
671
  //copy uv packed to u,v planes (1/2 the width and 1/2 the height of y)
672
  uint8_t *d_u = pBuffer->m_u_buffer_ptr;
673
  uint8_t *d_v = pBuffer->m_v_buffer_ptr;
674
  for (int y = 0; y < h/2; y++)
675
  {
676
    uint8_t *s_uv = procOut->UVbuff + (y * stride);
677
    for (int x = 0; x < w/2; x++)
678
    {
679
      *d_u++ = *s_uv++;
680
      *d_v++ = *s_uv++;
681
    }
682
  }
683
}
684
685
void CMPCOutputThread::CopyOutAsYV12DeInterlace(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride)
686
{
687
  // copy luma
688
  uint8_t *s_y = procOut->Ybuff;
689
  uint8_t *d_y = pBuffer->m_y_buffer_ptr;
690
  for (int y = 0; y < h/2; y++, s_y += stride)
691
  {
692
    memcpy(d_y, s_y, w);
693
    d_y += w;
694
    memcpy(d_y, s_y, w);
695
    d_y += w;
696
  }
697
  //copy chroma
698
  //copy uv packed to u,v planes (1/2 the width and 1/2 the height of y)
699
  uint8_t *d_u = pBuffer->m_u_buffer_ptr;
700
  uint8_t *d_v = pBuffer->m_v_buffer_ptr;
701
  for (int y = 0; y < h/4; y++)
702
  {
703
    uint8_t *s_uv = procOut->UVbuff + (y * stride);
704
    for (int x = 0; x < w/2; x++)
705
    {
706
      *d_u++ = *s_uv++;
707
      *d_v++ = *s_uv++;
708
    }
709
    s_uv = procOut->UVbuff + (y * stride);
710
    for (int x = 0; x < w/2; x++)
711
    {
712
      *d_u++ = *s_uv++;
713
      *d_v++ = *s_uv++;
714
    }
715
  }
716
717
  pBuffer->m_interlace = false;
718
}
719
720
void CMPCOutputThread::CopyOutAsNV12(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride)
721
{
722
  if (w == stride)
723
  {
724
    int bytes = w * h;
725
    // copy y
726
    memcpy(pBuffer->m_y_buffer_ptr, procOut->Ybuff, bytes);
727
    // copy uv
728
    memcpy(pBuffer->m_uv_buffer_ptr, procOut->UVbuff, bytes/2 );
729
  }
730
  else
731
  {
732
    // copy y
733
    uint8_t *s = procOut->Ybuff;
734
    uint8_t *d = pBuffer->m_y_buffer_ptr;
735
    for (int y = 0; y < h; y++, s += stride, d += w)
736
      memcpy(d, s, w);
737
    // copy uv
738
    s = procOut->UVbuff;
739
    d = pBuffer->m_uv_buffer_ptr;
740
    for (int y = 0; y < h/2; y++, s += stride, d += w)
741
      memcpy(d, s, w);
742
  }
743
}
744
745
void CMPCOutputThread::CopyOutAsNV12DeInterlace(CPictureBuffer *pBuffer, BCM::BC_DTS_PROC_OUT *procOut, int w, int h, int stride)
746
{
747
  // do simple line doubling de-interlacing.
748
  // copy luma
749
  uint8_t *s_y = procOut->Ybuff;
750
  uint8_t *d_y = pBuffer->m_y_buffer_ptr;
751
  for (int y = 0; y < h/2; y++, s_y += stride)
752
  {
753
    memcpy(d_y, s_y, w);
754
    d_y += w;
755
    memcpy(d_y, s_y, w);
756
    d_y += w;
757
  }
758
  //copy chroma
759
  uint8_t *s_uv = procOut->UVbuff;
760
  uint8_t *d_uv = pBuffer->m_uv_buffer_ptr;
761
  for (int y = 0; y < h/4; y++, s_uv += stride) {
762
    memcpy(d_uv, s_uv, w);
763
    d_uv += w;
764
    memcpy(d_uv, s_uv, w);
765
    d_uv += w;
766
  }
767
  pBuffer->m_interlace = false;
768
}
769
770
void CMPCOutputThread::CheckUpperLeftGreenPixelHack(CPictureBuffer *pBuffer)
771
{
772
  // crystalhd driver sends internal info in 1st pixel location, then restores
773
  // original pixel value but sometimes, the info is broked and the
774
  // driver cannot do the restore and zeros the pixel. This is wrong for
775
  // yuv color space, uv values should be set to 128 otherwise we get a
776
  // bright green pixel in upper left.
777
  // We fix this by replicating the 2nd pixel to the 1st.
778
  switch(pBuffer->m_format)
779
  {
780
    default:
781
    case RENDER_FMT_YUV420P:
782
    {
783
      uint8_t *d_y = pBuffer->m_y_buffer_ptr;
784
      uint8_t *d_u = pBuffer->m_u_buffer_ptr;
785
      uint8_t *d_v = pBuffer->m_v_buffer_ptr;
786
      d_y[0] = d_y[1];
787
      d_u[0] = d_u[1];
788
      d_v[0] = d_v[1];
789
    }
790
    break;
791
792
    case RENDER_FMT_NV12:
793
    {
794
      uint8_t  *d_y  = pBuffer->m_y_buffer_ptr;
795
      uint16_t *d_uv = (uint16_t*)pBuffer->m_uv_buffer_ptr;
796
      d_y[0] = d_y[1];
797
      d_uv[0] = d_uv[1];
798
    }
799
    break;
800
801
    case RENDER_FMT_YUYV422:
802
    {
803
      uint32_t *d_yuyv = (uint32_t*)pBuffer->m_y_buffer_ptr;
804
      d_yuyv[0] = d_yuyv[1];
805
    }
806
    break;
807
  }
808
}
809
810
bool CMPCOutputThread::GetDecoderOutput(void)
811
{
812
  BCM::BC_STATUS ret;
813
  BCM::BC_DTS_PROC_OUT procOut;
814
  CPictureBuffer *pBuffer = NULL;
815
  bool got_picture = false;
816
817
  // Setup output struct
818
  memset(&procOut, 0, sizeof(BCM::BC_DTS_PROC_OUT));
819
820
  // Fetch data from the decoder
821
  ret = m_dll->DtsProcOutputNoCopy(m_device, m_timeout, &procOut);
822
823
  switch (ret)
824
  {
825
    case BCM::BC_STS_SUCCESS:
826
      if (m_format_valid && (procOut.PoutFlags & BCM::BC_POUT_FLAGS_PIB_VALID))
827
      {
828
        if (procOut.PicInfo.timeStamp && 
829
          m_timestamp != procOut.PicInfo.timeStamp &&
830
          m_width == (int)procOut.PicInfo.width && 
831
          m_height == (int)procOut.PicInfo.height)
832
        {
833
          m_timestamp = procOut.PicInfo.timeStamp;
834
          m_PictureNumber = procOut.PicInfo.picture_number;
835
836
          if (m_framerate_tracking)
837
            DoFrameRateTracking((double)m_timestamp / 1000.0);
838
839
          // do not let FreeList to get greater than 10
840
          if (m_FreeList.Count() > 10)
841
            delete m_FreeList.Pop();
842
843
          // Get next output buffer from the free list
844
          pBuffer = m_FreeList.Pop();
845
          if (!pBuffer)
846
          {
847
            // No free pre-allocated buffers so make one
848
            if (m_output_YV12)
849
            {
850
              // output YV12, nouveau driver has slow NV12, YUY2 capability.
851
              pBuffer = new CPictureBuffer(RENDER_FMT_YUV420P, m_width, m_height);
852
            }
853
            else
854
            {
855
              if (m_color_space == BCM::MODE422_YUY2)
856
                pBuffer = new CPictureBuffer(RENDER_FMT_YUYV422, m_width, m_height);
857
              else
858
                pBuffer = new CPictureBuffer(RENDER_FMT_NV12, m_width, m_height);
859
            }
860
861
            CLog::Log(LOGDEBUG, "%s: Added a new Buffer, ReadyListCount: %d", __MODULE_NAME__, m_ReadyList.Count());
862
            while (!m_bStop && m_ReadyList.Count() > 10)
863
              Sleep(1);
864
          }
865
866
          pBuffer->m_width = m_width;
867
          pBuffer->m_height = m_height;
868
          pBuffer->m_field = CRYSTALHD_FIELD_FULL;
869
          pBuffer->m_interlace = m_interlace > 0 ? true : false;
870
          pBuffer->m_framerate = m_framerate;
871
          pBuffer->m_timestamp = m_timestamp;
872
          pBuffer->m_color_space = m_color_space;
873
          pBuffer->m_color_range = m_color_range;
874
          pBuffer->m_color_matrix = m_color_matrix;
875
          pBuffer->m_PictureNumber = m_PictureNumber;
876
877
          int w = m_width;
878
          int h = m_height;
879
          // frame that are not equal in width to 720, 1280 or 1920
880
          // need to be copied by a quantized stride (possible lib/driver bug) so force it.
881
          int stride = m_width;
882
          if (!m_has_bcm70015)
883
          {
884
            // bcm70012 uses quantized strides
885
            if (w <= 720)
886
              stride = 720;
887
            else if (w <= 1280)
888
              stride = 1280;
889
            else
890
              stride = 1920;
891
          }
892
893
          if (pBuffer->m_color_space == BCM::MODE420)
894
          {
895
            switch(pBuffer->m_format)
896
            {
897
              case RENDER_FMT_NV12:
898
                if (pBuffer->m_interlace)
899
                  CopyOutAsNV12DeInterlace(pBuffer, &procOut, w, h, stride);
900
                else
901
                  CopyOutAsNV12(pBuffer, &procOut, w, h, stride);
902
              break;
903
              case RENDER_FMT_YUV420P:
904
                if (pBuffer->m_interlace)
905
                  CopyOutAsYV12DeInterlace(pBuffer, &procOut, w, h, stride);
906
                else
907
                  CopyOutAsYV12(pBuffer, &procOut, w, h, stride);
908
              break;
909
              default:
910
              break;
911
            }
912
          }
913
          else
914
          {
915
            switch(pBuffer->m_format)
916
            {
917
              case RENDER_FMT_YUYV422:
918
                if (pBuffer->m_interlace)
919
                {
920
                  // do simple line doubling de-interlacing.
921
                  // copy luma
922
                  int yuy2_w = w * 2;
923
                  int yuy2_stride = stride*2;
924
                  uint8_t *s_y = procOut.Ybuff;
925
                  uint8_t *d_y = pBuffer->m_y_buffer_ptr;
926
                  for (int y = 0; y < h/2; y++, s_y += yuy2_stride)
927
                  {
928
                    memcpy(d_y, s_y, yuy2_w);
929
                    d_y += yuy2_w;
930
                    memcpy(d_y, s_y, yuy2_w);
931
                    d_y += yuy2_w;
932
                  }
933
                  pBuffer->m_interlace = false;
934
                }
935
                else
936
                {
937
                  memcpy(pBuffer->m_y_buffer_ptr,  procOut.Ybuff, pBuffer->m_y_buffer_size);
938
                }
939
              break;
940
              case RENDER_FMT_YUV420P:
941
                // TODO: deinterlace for yuy2 -> yv12, icky
942
                {
943
                  // Perform the color space conversion.
944
                  uint8_t* src[] =       { procOut.Ybuff, NULL, NULL, NULL };
945
                  int      srcStride[] = { stride*2, 0, 0, 0 };
946
                  uint8_t* dst[] =       { pBuffer->m_y_buffer_ptr, pBuffer->m_u_buffer_ptr, pBuffer->m_v_buffer_ptr, NULL };
947
                  int      dstStride[] = { pBuffer->m_width, pBuffer->m_width/2, pBuffer->m_width/2, 0 };
948
949
                  m_sw_scale_ctx = sws_getCachedContext(m_sw_scale_ctx,
950
                    pBuffer->m_width, pBuffer->m_height, PIX_FMT_YUYV422,
951
                    pBuffer->m_width, pBuffer->m_height, PIX_FMT_YUV420P,
952
                    SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);
953
                  sws_scale(m_sw_scale_ctx, src, srcStride, 0, pBuffer->m_height, dst, dstStride);
954
                }
955
              break;
956
              default:
957
              break;
958
            }
959
          }
960
961
          CheckUpperLeftGreenPixelHack(pBuffer);
962
          m_ReadyList.Push(pBuffer);
963
          m_ready_event.Set();
964
          got_picture = true;
965
        }
966
        else
967
        {
968
          if (m_PictureNumber != procOut.PicInfo.picture_number)
969
            CLog::Log(LOGDEBUG, "%s: No timestamp detected: %" PRIu64, __MODULE_NAME__, procOut.PicInfo.timeStamp);
970
          m_PictureNumber = procOut.PicInfo.picture_number;
971
        }
972
      }
973
974
      m_dll->DtsReleaseOutputBuffs(m_device, NULL, FALSE);
975
    break;
976
977
    case BCM::BC_STS_FMT_CHANGE:
978
      CLog::Log(LOGDEBUG, "%s: Format Change Detected. Flags: 0x%08x", __MODULE_NAME__, procOut.PoutFlags);
979
      if ((procOut.PoutFlags & BCM::BC_POUT_FLAGS_PIB_VALID) && (procOut.PoutFlags & BCM::BC_POUT_FLAGS_FMT_CHANGE))
980
      {
981
        PrintFormat(procOut.PicInfo);
982
983
        if (procOut.PicInfo.height == 1088) {
984
          procOut.PicInfo.height = 1080;
985
        }
986
        m_width = procOut.PicInfo.width;
987
        m_height = procOut.PicInfo.height;
988
        m_timestamp = DVD_NOPTS_VALUE;
989
        m_color_space = procOut.b422Mode;
990
        m_color_range = 0;
991
        m_color_matrix = procOut.PicInfo.colour_primaries;
992
        SetAspectRatio(&procOut.PicInfo);
993
        SetFrameRate(procOut.PicInfo.frame_rate);
994
        if (procOut.PicInfo.flags & VDEC_FLAG_INTERLACED_SRC)
995
        {
996
          m_interlace = true;
997
        }
998
        m_timeout = 2000;
999
        m_format_valid = true;
1000
        m_ready_event.Set();
1001
      }
1002
    break;
1003
1004
    case BCM::BC_STS_DEC_NOT_OPEN:
1005
    break;
1006
1007
    case BCM::BC_STS_DEC_NOT_STARTED:
1008
    break;
1009
1010
    case BCM::BC_STS_IO_USER_ABORT:
1011
    break;
1012
1013
    case BCM::BC_STS_NO_DATA:
1014
    break;
1015
1016
    case BCM::BC_STS_TIMEOUT:
1017
    break;
1018
1019
    default:
1020
      if (ret > 26)
1021
        CLog::Log(LOGDEBUG, "%s: DtsProcOutput returned %d.", __MODULE_NAME__, ret);
1022
      else
1023
        CLog::Log(LOGDEBUG, "%s: DtsProcOutput returned %s.", __MODULE_NAME__, g_DtsStatusText[ret]);
1024
    break;
1025
  }
1026
  
1027
  return got_picture;
1028
}
1029
1030
void CMPCOutputThread::Process(void)
1031
{
1032
  BCM::BC_STATUS ret;
1033
  BCM::BC_DTS_STATUS decoder_status;
1034
1035
  m_PictureNumber = 0;
1036
1037
  CLog::Log(LOGDEBUG, "%s: Output Thread Started...", __MODULE_NAME__);
1038
1039
  // wait for decoder startup, calls into DtsProcOutputXXCopy will
1040
  // return immediately until decoder starts getting input packets. 
1041
  while (!m_bStop)
1042
  {
1043
    memset(&decoder_status, 0, sizeof(decoder_status));
1044
    ret = m_dll->DtsGetDriverStatus(m_device, &decoder_status);
1045
    if (ret == BCM::BC_STS_SUCCESS && decoder_status.ReadyListCount)
1046
    {
1047
      GetDecoderOutput();
1048
      break;
1049
    }
1050
    Sleep(10);
1051
  }
1052
1053
  // decoder is primed so now calls in DtsProcOutputXXCopy will block
1054
  while (!m_bStop)
1055
  {
1056
    memset(&decoder_status, 0, sizeof(decoder_status));
1057
    ret = m_dll->DtsGetDriverStatus(m_device, &decoder_status);
1058
    if (ret == BCM::BC_STS_SUCCESS && decoder_status.ReadyListCount != 0)
1059
      GetDecoderOutput();
1060
    else
1061
      Sleep(1);
1062
1063
#ifdef USE_CHD_SINGLE_THREADED_API
1064
    while (!m_bStop)
1065
    {
1066
      ret = m_dll->DtsGetDriverStatus(m_device, &decoder_status);
1067
      if (ret == BCM::BC_STS_SUCCESS && decoder_status.ReadyListCount != 0)
1068
      {
1069
        double pts = (double)decoder_status.NextTimeStamp / 1000.0;
1070
        fprintf(stdout, "cpbEmptySize(%d), NextTimeStamp(%f)\n", decoder_status.cpbEmptySize, pts);
1071
        break;
1072
      }
1073
      Sleep(10);
1074
    }
1075
#endif
1076
  }
1077
  CLog::Log(LOGDEBUG, "%s: Output Thread Stopped...", __MODULE_NAME__);
1078
}
1079
1080
////////////////////////////////////////////////////////////////////////////////////////////
1081
#if defined(TARGET_DARWIN)
1082
#pragma mark -
1083
#endif
1084
CCrystalHD* CCrystalHD::m_pInstance = NULL;
1085
1086
CCrystalHD::CCrystalHD() :
1087
  m_device(NULL),
1088
  m_device_preset(false),
1089
  m_new_lib(false),
1090
  m_decoder_open(false),
1091
  m_has_bcm70015(false),
1092
  m_color_space(BCM::MODE420),
1093
  m_drop_state(false),
1094
  m_skip_state(false),
1095
  m_timeout(0),
1096
  m_wait_timeout(0),
1097
  m_field(0),
1098
  m_width(0),
1099
  m_height(0),
1100
  m_reset(0),
1101
  m_last_pict_num(0),
1102
  m_last_demuxer_pts(0.0),
1103
  m_last_decoder_pts(0.0),
1104
  m_pOutputThread(NULL),
1105
  m_sps_pps_size(0),
1106
  m_convert_bitstream(false)
1107
{
1108
#if (HAVE_LIBCRYSTALHD == 2)
1109
  memset(&m_bc_info_crystal, 0, sizeof(m_bc_info_crystal));
1110
#endif
1111
1112
  memset(&m_chd_params, 0, sizeof(m_chd_params));
1113
  memset(&m_sps_pps_context, 0, sizeof(m_sps_pps_context));
1114
1115
  m_dll = new DllLibCrystalHD;
1116
#ifdef TARGET_WINDOWS
1117
  std::string  strDll;
1118
  if(CWIN32Util::GetCrystalHDLibraryPath(strDll) && m_dll->SetFile(strDll) && m_dll->Load() && m_dll->IsLoaded() )
1119
#else
1120
  if (m_dll->Load() && m_dll->IsLoaded() )
1121
#endif
1122
  {
1123
#if (HAVE_LIBCRYSTALHD == 2)
1124
    m_new_lib = m_dll->LoadNewLibFunctions();
1125
#endif
1126
1127
    OpenDevice();
1128
    
1129
#if (HAVE_LIBCRYSTALHD == 2)
1130
    if (m_device && m_new_lib)
1131
    {
1132
      m_dll->DtsCrystalHDVersion(m_device, (BCM::PBC_INFO_CRYSTAL)&m_bc_info_crystal);
1133
      m_has_bcm70015 = (m_bc_info_crystal.device == 1);
1134
      // bcm70012 can do nv12 (420), yuy2 (422) and uyvy (422)
1135
      // bcm70015 can do only yuy2 (422)
1136
      if (m_has_bcm70015)
1137
        m_color_space = BCM::OUTPUT_MODE422_YUY2;
1138
    }
1139
#endif
1140
  }
1141
1142
  // delete dll if device open fails, minimizes ram footprint
1143
  if (!m_device)
1144
  {
1145
    delete m_dll;
1146
    m_dll = NULL;
1147
    CLog::Log(LOGDEBUG, "%s: broadcom crystal hd not found", __MODULE_NAME__);
1148
  }
1149
  else
1150
  {
1151
    // we know there's a device present now, close the device until doing playback
1152
    CloseDevice();
1153
  }
1154
}
1155
1156
1157
CCrystalHD::~CCrystalHD()
1158
{
1159
  if (m_decoder_open)
1160
    CloseDecoder();
1161
1162
  if (m_device)
1163
    CloseDevice();
1164
1165
  if (m_dll)
1166
    delete m_dll;
1167
}
1168
1169
1170
bool CCrystalHD::DevicePresent(void)
1171
{
1172
  return m_device_preset;
1173
}
1174
1175
void CCrystalHD::RemoveInstance(void)
1176
{
1177
  if (m_pInstance)
1178
  {
1179
    delete m_pInstance;
1180
    m_pInstance = NULL;
1181
  }
1182
}
1183
1184
CCrystalHD* CCrystalHD::GetInstance(void)
1185
{
1186
  if (!m_pInstance)
1187
  {
1188
    m_pInstance = new CCrystalHD();
1189
  }
1190
  return m_pInstance;
1191
}
1192
1193
void CCrystalHD::OpenDevice()
1194
{
1195
  uint32_t mode = BCM::DTS_PLAYBACK_MODE          |
1196
                  BCM::DTS_LOAD_FILE_PLAY_FW      |
1197
#ifdef USE_CHD_SINGLE_THREADED_API
1198
                  BCM::DTS_SINGLE_THREADED_MODE   |
1199
#endif
1200
                  BCM::DTS_SKIP_TX_CHK_CPB        |
1201
                  BCM::DTS_PLAYBACK_DROP_RPT_MODE |
1202
                  DTS_DFLT_RESOLUTION(BCM::vdecRESOLUTION_720p23_976);
1203
1204
  BCM::BC_STATUS res= m_dll->DtsDeviceOpen(&m_device, mode);
1205
  if (res != BCM::BC_STS_SUCCESS)
1206
  {
1207
    m_device = NULL;
1208
    if( res == BCM::BC_STS_DEC_EXIST_OPEN )
1209
      CLog::Log(LOGDEBUG, "%s: device owned by another application", __MODULE_NAME__);
1210
    else
1211
      CLog::Log(LOGDEBUG, "%s: device open failed , returning(0x%x)", __MODULE_NAME__, res);
1212
    m_device_preset = false;
1213
  }
1214
  else
1215
  {
1216
    #if (HAVE_LIBCRYSTALHD == 2)
1217
      if (m_new_lib)
1218
        CLog::Log(LOGDEBUG, "%s(new API): device opened", __MODULE_NAME__);
1219
      else
1220
        CLog::Log(LOGDEBUG, "%s(old API): device opened", __MODULE_NAME__);
1221
    #else
1222
      CLog::Log(LOGDEBUG, "%s: device opened", __MODULE_NAME__);
1223
    #endif
1224
    m_device_preset = true;
1225
  }
1226
}
1227
1228
void CCrystalHD::CloseDevice()
1229
{
1230
  if (m_device)
1231
  {
1232
    m_dll->DtsDeviceClose(m_device);
1233
    m_device = NULL;
1234
    CLog::Log(LOGDEBUG, "%s: device closed", __MODULE_NAME__);
1235
  }
1236
}
1237
1238
bool CCrystalHD::OpenDecoder(CRYSTALHD_CODEC_TYPE codec_type, CDVDStreamInfo &hints)
1239
{
1240
  BCM::BC_STATUS res;
1241
  uint32_t StreamType;
1242
#if (HAVE_LIBCRYSTALHD == 2)
1243
  BCM::BC_MEDIA_SUBTYPE Subtype;
1244
#endif
1245
1246
  if (!m_device_preset)
1247
    return false;
1248
1249
  if (m_decoder_open)
1250
    CloseDecoder();
1251
    
1252
  OpenDevice();
1253
  if (!m_device)
1254
    return false;
1255
1256
#if (HAVE_LIBCRYSTALHD == 2) && defined(TARGET_WINDOWS)
1257
  // Drivers prior to 3.6.9.32 don't have proper support for CRYSTALHD_CODEC_ID_AVC1
1258
  // The internal version numbers are different for some reason...
1259
  if (   (m_bc_info_crystal.dilVersion.dilRelease < 3)
1260
      || (m_bc_info_crystal.dilVersion.dilRelease == 3 && m_bc_info_crystal.dilVersion.dilMajor < 22)
1261
      || (m_bc_info_crystal.drvVersion.drvRelease < 3)
1262
      || (m_bc_info_crystal.drvVersion.drvRelease == 3 && m_bc_info_crystal.drvVersion.drvMajor < 7) )
1263
  {
1264
    CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, "CrystalHD", g_localizeStrings.Get(2101));
1265
    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.");
1266
1267
    if (codec_type == CRYSTALHD_CODEC_ID_AVC1)
1268
      return false;
1269
  }
1270
#endif
1271
1272
  uint32_t videoAlg = 0;
1273
  switch (codec_type)
1274
  {
1275
    case CRYSTALHD_CODEC_ID_VC1:
1276
      videoAlg = BCM::BC_VID_ALGO_VC1;
1277
      StreamType = BCM::BC_STREAM_TYPE_ES;
1278
      m_convert_bitstream = false;
1279
    break;
1280
    case CRYSTALHD_CODEC_ID_WVC1:
1281
      videoAlg = BCM::BC_VID_ALGO_VC1MP;
1282
      StreamType = BCM::BC_STREAM_TYPE_ES;
1283
      m_convert_bitstream = false;
1284
    break;
1285
    case CRYSTALHD_CODEC_ID_WMV3:
1286
      if (!m_has_bcm70015)
1287
        return false;
1288
      videoAlg = BCM::BC_VID_ALGO_VC1MP;
1289
      StreamType = BCM::BC_STREAM_TYPE_ES;
1290
      m_convert_bitstream = false;
1291
    break;
1292
    case CRYSTALHD_CODEC_ID_H264:
1293
      videoAlg = BCM::BC_VID_ALGO_H264;
1294
      StreamType = BCM::BC_STREAM_TYPE_ES;
1295
      m_convert_bitstream = false;
1296
    break;
1297
    case CRYSTALHD_CODEC_ID_AVC1:
1298
      videoAlg = BCM::BC_VID_ALGO_H264;
1299
      StreamType = BCM::BC_STREAM_TYPE_ES;
1300
      if (!m_new_lib)
1301
        m_convert_bitstream = bitstream_convert_init((uint8_t*)hints.extradata, hints.extrasize);
1302
      else
1303
        m_convert_bitstream = false;
1304
    break;
1305
    case CRYSTALHD_CODEC_ID_MPEG2:
1306
      videoAlg = BCM::BC_VID_ALGO_MPEG2;
1307
      StreamType = BCM::BC_STREAM_TYPE_ES;
1308
      m_convert_bitstream = false;
1309
    break;
1310
    //BC_VID_ALGO_DIVX:
1311
    //BC_VID_ALGO_VC1MP:
1312
    default:
1313
      return false;
1314
    break;
1315
  }
1316
  
1317
#if (HAVE_LIBCRYSTALHD == 2)
1318
  uint8_t *pMetaData = NULL;
1319
  uint32_t metaDataSz = 0;
1320
  uint32_t startCodeSz = 4;
1321
  m_chd_params.sps_pps_buf = NULL;
1322
  switch (codec_type)
1323
  {
1324
    case CRYSTALHD_CODEC_ID_VC1:
1325
      Subtype = BCM::BC_MSUBTYPE_VC1;
1326
      pMetaData = (uint8_t*)hints.extradata;
1327
      metaDataSz = hints.extrasize;
1328
    break;
1329
    case CRYSTALHD_CODEC_ID_WVC1:
1330
      Subtype = BCM::BC_MSUBTYPE_WVC1;
1331
    break;
1332
    case CRYSTALHD_CODEC_ID_WMV3:
1333
      Subtype = BCM::BC_MSUBTYPE_WMV3;
1334
      pMetaData = (uint8_t*)hints.extradata;
1335
      metaDataSz = hints.extrasize;
1336
    break;
1337
    case CRYSTALHD_CODEC_ID_H264:
1338
      Subtype = BCM::BC_MSUBTYPE_H264;
1339
      pMetaData = (uint8_t*)hints.extradata;
1340
      metaDataSz = hints.extrasize;
1341
    break;
1342
    case CRYSTALHD_CODEC_ID_AVC1:
1343
      Subtype = BCM::BC_MSUBTYPE_AVC1;
1344
      m_chd_params.sps_pps_buf = (uint8_t*)malloc(1000);
1345
			if (!extract_sps_pps_from_avcc(hints.extrasize, hints.extradata))
1346
      {
1347
        free(m_chd_params.sps_pps_buf);
1348
        m_chd_params.sps_pps_buf = NULL;
1349
			}
1350
      else
1351
      {
1352
        pMetaData = m_chd_params.sps_pps_buf;
1353
        metaDataSz = m_chd_params.sps_pps_size;
1354
        startCodeSz = m_chd_params.nal_size_bytes;
1355
      }
1356
    break;
1357
    case CRYSTALHD_CODEC_ID_MPEG2:
1358
      Subtype = BCM::BC_MSUBTYPE_MPEG2VIDEO;
1359
      pMetaData = (uint8_t*)hints.extradata;
1360
      metaDataSz = hints.extrasize;
1361
    break;
1362
    //BC_VID_ALGO_DIVX:
1363
    //BC_VID_ALGO_VC1MP:
1364
  }
1365
#endif
1366
1367
  do
1368
  {
1369
#if (HAVE_LIBCRYSTALHD == 2)
1370
    if (m_new_lib)
1371
    {
1372
      BCM::BC_INPUT_FORMAT bcm_input_format;
1373
      memset(&bcm_input_format, 0, sizeof(BCM::BC_INPUT_FORMAT));
1374
1375
      bcm_input_format.FGTEnable = FALSE;
1376
      bcm_input_format.Progressive = TRUE;
1377
      bcm_input_format.OptFlags = 0x80000000 | BCM::vdecFrameRate23_97;
1378
      #ifdef USE_CHD_SINGLE_THREADED_API
1379
        bcm_input_format.OptFlags |= 0x80;
1380
      #endif
1381
      
1382
      bcm_input_format.width = hints.width;
1383
      bcm_input_format.height = hints.height;
1384
      bcm_input_format.mSubtype = Subtype;
1385
      bcm_input_format.pMetaData = pMetaData;
1386
      bcm_input_format.metaDataSz = metaDataSz;
1387
      bcm_input_format.startCodeSz = startCodeSz;
1388
1389
      res = m_dll->DtsSetInputFormat(m_device, &bcm_input_format);
1390
      if (res != BCM::BC_STS_SUCCESS)
1391
      {
1392
        CLog::Log(LOGERROR, "%s: set input format failed", __MODULE_NAME__);
1393
        break;
1394
      }
1395
1396
      res = m_dll->DtsOpenDecoder(m_device, StreamType);
1397
      if (res != BCM::BC_STS_SUCCESS)
1398
      {
1399
        CLog::Log(LOGERROR, "%s: open decoder failed", __MODULE_NAME__);
1400
        break;
1401
      }
1402
1403
      if (m_has_bcm70015)
1404
        res = m_dll->DtsSetColorSpace(m_device, BCM::OUTPUT_MODE422_YUY2); 
1405
      else
1406
        res = m_dll->DtsSetColorSpace(m_device, BCM::OUTPUT_MODE420); 
1407
      if (res != BCM::BC_STS_SUCCESS)
1408
      { 
1409
        CLog::Log(LOGERROR, "%s: set color space failed", __MODULE_NAME__); 
1410
        break; 
1411
      }
1412
    }
1413
    else
1414
#endif
1415
    {
1416
      res = m_dll->DtsOpenDecoder(m_device, StreamType);
1417
      if (res != BCM::BC_STS_SUCCESS)
1418
      {
1419
        CLog::Log(LOGERROR, "%s: open decoder failed", __MODULE_NAME__);
1420
        break;
1421
      }
1422
1423
      uint32_t OptFlags = 0x80000000 | BCM::vdecFrameRate23_97;
1424
      res = m_dll->DtsSetVideoParams(m_device, videoAlg, FALSE, FALSE, TRUE, OptFlags);
1425
      if (res != BCM::BC_STS_SUCCESS)
1426
      {
1427
        CLog::Log(LOGERROR, "%s: set video params failed", __MODULE_NAME__);
1428
        break;
1429
      }
1430
    }
1431
    
1432
    res = m_dll->DtsStartDecoder(m_device);
1433
    if (res != BCM::BC_STS_SUCCESS)
1434
    {
1435
      CLog::Log(LOGERROR, "%s: start decoder failed", __MODULE_NAME__);
1436
      break;
1437
    }
1438
1439
    res = m_dll->DtsStartCapture(m_device);
1440
    if (res != BCM::BC_STS_SUCCESS)
1441
    {
1442
      CLog::Log(LOGERROR, "%s: start capture failed", __MODULE_NAME__);
1443
      break;
1444
    }
1445
1446
    m_pOutputThread = new CMPCOutputThread(m_device, m_dll, m_has_bcm70015);
1447
    m_pOutputThread->Create();
1448
1449
    m_drop_state = false;
1450
    m_skip_state = false;
1451
    m_decoder_open = true;
1452
    // set output timeout to 1ms during startup,
1453
    // this will get reset once we get a picture back.
1454
    // the effect is to speed feeding demux packets during startup.
1455
    m_wait_timeout = 1;
1456
    m_reset = 0;
1457
    m_last_pict_num = 0;
1458
    m_last_demuxer_pts = DVD_NOPTS_VALUE;
1459
    m_last_decoder_pts = DVD_NOPTS_VALUE;
1460
  } while(false);
1461
1462
  return m_decoder_open;
1463
}
1464
1465
void CCrystalHD::CloseDecoder(void)
1466
{
1467
  if (m_pOutputThread)
1468
  {
1469
    while(m_BusyList.Count())
1470
      m_pOutputThread->FreeListPush( m_BusyList.Pop() );
1471
1472
    m_pOutputThread->StopThread();
1473
    delete m_pOutputThread;
1474
    m_pOutputThread = NULL;
1475
  }
1476
1477
  if (m_convert_bitstream)
1478
  {
1479
    if (m_sps_pps_context.sps_pps_data)
1480
    {
1481
      free(m_sps_pps_context.sps_pps_data);
1482
      m_sps_pps_context.sps_pps_data = NULL;
1483
    }
1484
  }
1485
#if (HAVE_LIBCRYSTALHD == 2)
1486
	if (m_chd_params.sps_pps_buf)
1487
  {
1488
		free(m_chd_params.sps_pps_buf);
1489
		m_chd_params.sps_pps_buf = NULL;
1490
	}
1491
#endif
1492
1493
  if (m_decoder_open)
1494
  {
1495
    // DtsFlushRxCapture must release internal queues when
1496
    // calling DtsStopDecoder/DtsCloseDecoder or the next
1497
    // DtsStartCapture will fail. This is a driver/lib bug
1498
    // with new chd driver. The existing driver ignores the
1499
    // bDiscardOnly arg.
1500
    if (!m_has_bcm70015)
1501
      m_dll->DtsFlushRxCapture(m_device, false);
1502
    m_dll->DtsStopDecoder(m_device);
1503
    m_dll->DtsCloseDecoder(m_device);
1504
    m_decoder_open = false;
1505
  }
1506
  
1507
  CloseDevice();
1508
}
1509
1510
void CCrystalHD::Reset(void)
1511
{
1512
  if (!m_has_bcm70015)
1513
  {
1514
    // Calling for non-error flush, Flushes all the decoder
1515
    //  buffers, input, decoded and to be decoded. 
1516
    m_reset = 10;
1517
    m_wait_timeout = 1;
1518
    m_dll->DtsFlushInput(m_device, 2);
1519
  }
1520
1521
  while (m_BusyList.Count())
1522
    m_pOutputThread->FreeListPush( m_BusyList.Pop() );
1523
1524
  while (m_pOutputThread->GetReadyCount())
1525
  {
1526
    ::Sleep(1);
1527
    m_pOutputThread->FreeListPush( m_pOutputThread->ReadyListPop() );
1528
  }
1529
}
1530
1531
bool CCrystalHD::AddInput(unsigned char *pData, size_t size, double dts, double pts)
1532
{
1533
  if (pData)
1534
  {
1535
    BCM::BC_STATUS ret;
1536
    uint64_t int_pts = pts * 1000;
1537
    int demuxer_bytes = size;
1538
    uint8_t *demuxer_content = pData;
1539
    bool free_demuxer_content  = false;
1540
1541
    if (m_convert_bitstream)
1542
    {
1543
      // convert demuxer packet from bitstream (AVC1) to bytestream (AnnexB)
1544
      int bytestream_size = 0;
1545
      uint8_t *bytestream_buff = NULL;
1546
1547
      bitstream_convert(demuxer_content, demuxer_bytes, &bytestream_buff, &bytestream_size);
1548
      if (bytestream_buff && (bytestream_size > 0))
1549
      {
1550
        if (bytestream_buff != demuxer_content)
1551
          free_demuxer_content = true;
1552
        demuxer_bytes = bytestream_size;
1553
        demuxer_content = bytestream_buff;
1554
      }
1555
    }
1556
1557
    do
1558
    {
1559
      ret = m_dll->DtsProcInput(m_device, demuxer_content, demuxer_bytes, int_pts, 0);
1560
      if (ret == BCM::BC_STS_SUCCESS)
1561
      {
1562
        m_last_demuxer_pts = pts;
1563
      }
1564
      else if (ret == BCM::BC_STS_BUSY)
1565
      {
1566
        CLog::Log(LOGDEBUG, "%s: DtsProcInput returned BC_STS_BUSY", __MODULE_NAME__);
1567
        ::Sleep(1); // Buffer is full, sleep it empty
1568
      }
1569
    } while (ret != BCM::BC_STS_SUCCESS);
1570
1571
    if (free_demuxer_content)
1572
      free(demuxer_content);
1573
1574
    if (!m_has_bcm70015)
1575
    {
1576
      if (m_reset)
1577
      {
1578
        m_reset--;
1579
        if (!m_skip_state)
1580
        {
1581
          m_skip_state = true;
1582
          m_dll->DtsSetSkipPictureMode(m_device, 1);
1583
        }
1584
      }
1585
      else
1586
      {
1587
        if (m_skip_state)
1588
        {
1589
          m_skip_state = false;
1590
          m_dll->DtsSetSkipPictureMode(m_device, 0);
1591
        }
1592
      }
1593
    }
1594
1595
    if (m_pOutputThread->GetReadyCount() < 1)
1596
      m_pOutputThread->WaitOutput(m_wait_timeout);
1597
  }
1598
1599
  return true;
1600
}
1601
1602
int CCrystalHD::GetReadyCount(void)
1603
{
1604
  if (m_pOutputThread)
1605
    return m_pOutputThread->GetReadyCount();
1606
  else
1607
    return 0;
1608
}
1609
1610
void CCrystalHD::BusyListFlush(void)
1611
{
1612
  if (m_pOutputThread)
1613
  {
1614
    while ( m_BusyList.Count())
1615
      m_pOutputThread->FreeListPush( m_BusyList.Pop() );
1616
  }
1617
}
1618
1619
bool CCrystalHD::GetPicture(DVDVideoPicture *pDvdVideoPicture)
1620
{
1621
  CPictureBuffer* pBuffer = m_pOutputThread->ReadyListPop();
1622
1623
  if (!pBuffer)
1624
    return false;
1625
1626
  // default both dts/pts to DVD_NOPTS_VALUE, if crystalhd drops a frame,
1627
  // we can't tell so we can not track dts through the decoder or with
1628
  // and external queue. pts will get set from m_timestamp.
1629
  pDvdVideoPicture->dts = DVD_NOPTS_VALUE;
1630
  pDvdVideoPicture->pts = DVD_NOPTS_VALUE;
1631
1632
  if (pBuffer->m_timestamp != 0)
1633
    pDvdVideoPicture->pts = (double)pBuffer->m_timestamp / 1000.0;
1634
1635
  pDvdVideoPicture->iWidth = pBuffer->m_width;
1636
  pDvdVideoPicture->iHeight = pBuffer->m_height;
1637
  pDvdVideoPicture->iDisplayWidth = pBuffer->m_width;
1638
  pDvdVideoPicture->iDisplayHeight = pBuffer->m_height;
1639
1640
  switch(pBuffer->m_format)
1641
  {
1642
    default:
1643
    case RENDER_FMT_NV12:
1644
      // Y plane
1645
      pDvdVideoPicture->data[0] = (uint8_t*)pBuffer->m_y_buffer_ptr;
1646
      pDvdVideoPicture->iLineSize[0] = pBuffer->m_width;
1647
      // UV packed plane
1648
      pDvdVideoPicture->data[1] = (uint8_t*)pBuffer->m_uv_buffer_ptr;
1649
      pDvdVideoPicture->iLineSize[1] = pBuffer->m_width;
1650
      // unused
1651
      pDvdVideoPicture->data[2] = NULL;
1652
      pDvdVideoPicture->iLineSize[2] = 0;
1653
    break;
1654
    case RENDER_FMT_YUYV422:
1655
      // YUV packed plane
1656
      pDvdVideoPicture->data[0] = (uint8_t*)pBuffer->m_y_buffer_ptr;
1657
      pDvdVideoPicture->iLineSize[0] = pBuffer->m_width * 2;
1658
      // unused
1659
      pDvdVideoPicture->data[1] = NULL;
1660
      pDvdVideoPicture->iLineSize[1] = 0;
1661
      // unused
1662
      pDvdVideoPicture->data[2] = NULL;
1663
      pDvdVideoPicture->iLineSize[2] = 0;
1664
    break;
1665
    case RENDER_FMT_YUV420P:
1666
      // Y plane
1667
      pDvdVideoPicture->data[0] = (uint8_t*)pBuffer->m_y_buffer_ptr;
1668
      pDvdVideoPicture->iLineSize[0] = pBuffer->m_width;
1669
      // U plane
1670
      pDvdVideoPicture->data[1] = (uint8_t*)pBuffer->m_u_buffer_ptr;
1671
      pDvdVideoPicture->iLineSize[1] = pBuffer->m_width / 2;
1672
      // V plane
1673
      pDvdVideoPicture->data[2] = (uint8_t*)pBuffer->m_v_buffer_ptr;
1674
      pDvdVideoPicture->iLineSize[2] = pBuffer->m_width / 2;
1675
    break;
1676
  }
1677
1678
  pDvdVideoPicture->iRepeatPicture = 0;
1679
  pDvdVideoPicture->iDuration = DVD_TIME_BASE / pBuffer->m_framerate;
1680
  m_wait_timeout = pDvdVideoPicture->iDuration/2000;
1681
  pDvdVideoPicture->color_range = pBuffer->m_color_range;
1682
  pDvdVideoPicture->color_matrix = pBuffer->m_color_matrix;
1683
  pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
1684
  pDvdVideoPicture->iFlags |= m_drop_state ? DVP_FLAG_DROPPED : 0;
1685
  pDvdVideoPicture->format = pBuffer->m_format;
1686
1687
  m_last_pict_num = pBuffer->m_PictureNumber;
1688
  m_last_decoder_pts = pDvdVideoPicture->pts;
1689
1690
  while( m_BusyList.Count())
1691
    m_pOutputThread->FreeListPush( m_BusyList.Pop() );
1692
1693
  m_BusyList.Push(pBuffer);
1694
  return true;
1695
}
1696
1697
void CCrystalHD::SetDropState(bool bDrop)
1698
{
1699
  if (m_drop_state != bDrop)
1700
  {
1701
    m_drop_state = bDrop;
1702
    
1703
    if (!m_has_bcm70015)
1704
    {
1705
      if (!m_reset)
1706
      {
1707
        if (m_drop_state)
1708
        {
1709
          if (!m_skip_state)
1710
          {
1711
            m_skip_state = true;
1712
            m_dll->DtsSetSkipPictureMode(m_device, 1);
1713
            Sleep(1);
1714
          }
1715
        }
1716
        else
1717
        {
1718
          if (m_skip_state)
1719
          {
1720
            m_skip_state = false;
1721
            m_dll->DtsSetSkipPictureMode(m_device, 0);
1722
            Sleep(1);
1723
          }
1724
        }
1725
      }
1726
    }
1727
  }
1728
  /*
1729
  CLog::Log(LOGDEBUG, "%s: m_drop_state(%d), GetFreeCount(%d), GetReadyCount(%d)", __MODULE_NAME__, 
1730
      m_drop_state, m_pOutputThread->GetFreeCount(), m_pOutputThread->GetReadyCount());
1731
  */
1732
}
1733
////////////////////////////////////////////////////////////////////////////////////////////
1734
bool CCrystalHD::extract_sps_pps_from_avcc(int extradata_size, void *extradata)
1735
{
1736
  // based on gstbcmdec.c (bcmdec_insert_sps_pps)
1737
  // which is Copyright(c) 2008 Broadcom Corporation.
1738
  // and Licensed LGPL 2.1
1739
1740
  uint8_t *data = (uint8_t*)extradata;
1741
  uint32_t data_size = extradata_size;
1742
  int profile;
1743
  unsigned int nal_size;
1744
  unsigned int num_sps, num_pps;
1745
1746
  m_chd_params.sps_pps_size = 0;
1747
1748
  profile = (data[1] << 16) | (data[2] << 8) | data[3];
1749
  CLog::Log(LOGDEBUG, "%s: profile %06x", __MODULE_NAME__, profile);
1750
1751
  m_chd_params.nal_size_bytes = (data[4] & 0x03) + 1;
1752
1753
  CLog::Log(LOGDEBUG, "%s: nal size %d", __MODULE_NAME__, m_chd_params.nal_size_bytes);
1754
1755
  num_sps = data[5] & 0x1f;
1756
  CLog::Log(LOGDEBUG, "%s: num sps %d", __MODULE_NAME__, num_sps);
1757
1758
  data += 6;
1759
  data_size -= 6;
1760
1761
  for (unsigned int i = 0; i < num_sps; i++)
1762
  {
1763
    if (data_size < 2)
1764
      return false;
1765
1766
    nal_size = (data[0] << 8) | data[1];
1767
    data += 2;
1768
    data_size -= 2;
1769
1770
    if (data_size < nal_size)
1771
			return false;
1772
1773
    m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size + 0] = 0;
1774
    m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size + 1] = 0;
1775
    m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size + 2] = 0;
1776
    m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size + 3] = 1;
1777
1778
    m_chd_params.sps_pps_size += 4;
1779
1780
    memcpy(m_chd_params.sps_pps_buf + m_chd_params.sps_pps_size, data, nal_size);
1781
    m_chd_params.sps_pps_size += nal_size;
1782
1783
    data += nal_size;
1784
    data_size -= nal_size;
1785
  }
1786
1787
  if (data_size < 1)
1788
    return false;
1789
1790
  num_pps = data[0];
1791
  data += 1;
1792
  data_size -= 1;
1793
1794
  for (unsigned int i = 0; i < num_pps; i++)
1795
  {
1796
    if (data_size < 2)
1797
      return false;
1798
1799
    nal_size = (data[0] << 8) | data[1];
1800
    data += 2;
1801
    data_size -= 2;
1802
1803
    if (data_size < nal_size)
1804
      return false;
1805
1806
    m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size+0] = 0;
1807
    m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size+1] = 0;
1808
    m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size+2] = 0;
1809
    m_chd_params.sps_pps_buf[m_chd_params.sps_pps_size+3] = 1;
1810
1811
    m_chd_params.sps_pps_size += 4;
1812
1813
    memcpy(m_chd_params.sps_pps_buf + m_chd_params.sps_pps_size, data, nal_size);
1814
    m_chd_params.sps_pps_size += nal_size;
1815
1816
    data += nal_size;
1817
    data_size -= nal_size;
1818
  }
1819
1820
  CLog::Log(LOGDEBUG, "%s: data size at end = %d ", __MODULE_NAME__, data_size);
1821
1822
  return true;
1823
}
1824
1825
1826
////////////////////////////////////////////////////////////////////////////////////////////
1827
bool CCrystalHD::bitstream_convert_init(void *in_extradata, int in_extrasize)
1828
{
1829
  // based on h264_mp4toannexb_bsf.c (ffmpeg)
1830
  // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
1831
  // and Licensed GPL 2.1 or greater
1832
1833
  m_sps_pps_size = 0;
1834
  m_sps_pps_context.sps_pps_data = NULL;
1835
  
1836
  // nothing to filter
1837
  if (!in_extradata || in_extrasize < 6)
1838
    return false;
1839
1840
  uint16_t unit_size;
1841
  uint32_t total_size = 0;
1842
  uint8_t *out = NULL, unit_nb, sps_done = 0;
1843
  const uint8_t *extradata = (uint8_t*)in_extradata + 4;
1844
  static const uint8_t nalu_header[4] = {0, 0, 0, 1};
1845
1846
  // retrieve length coded size
1847
  m_sps_pps_context.length_size = (*extradata++ & 0x3) + 1;
1848
  if (m_sps_pps_context.length_size == 3)
1849
    return false;
1850
1851
  // retrieve sps and pps unit(s)
1852
  unit_nb = *extradata++ & 0x1f;  // number of sps unit(s)
1853
  if (!unit_nb)
1854
  {
1855
    unit_nb = *extradata++;       // number of pps unit(s)
1856
    sps_done++;
1857
  }
1858
  while (unit_nb--)
1859
  {
1860
    unit_size = extradata[0] << 8 | extradata[1];
1861
    total_size += unit_size + 4;
1862
    if ( (extradata + 2 + unit_size) > ((uint8_t*)in_extradata + in_extrasize) )
1863
    {
1864
      free(out);
1865
      return false;
1866
    }
1867
    uint8_t* new_out = (uint8_t*)realloc(out, total_size);
1868
    if (new_out)
1869
    {
1870
      out = new_out;
1871
    }
1872
    else
1873
    {
1874
      CLog::Log(LOGERROR, "bitstream_convert_init failed - %s : could not realloc the buffer out",  __FUNCTION__);
1875
      free(out);
1876
      return false;
1877
    }
1878
1879
    memcpy(out + total_size - unit_size - 4, nalu_header, 4);
1880
    memcpy(out + total_size - unit_size, extradata + 2, unit_size);
1881
    extradata += 2 + unit_size;
1882
1883
    if (!unit_nb && !sps_done++)
1884
      unit_nb = *extradata++;     // number of pps unit(s)
1885
  }
1886
1887
  m_sps_pps_context.sps_pps_data = out;
1888
  m_sps_pps_context.size = total_size;
1889
  m_sps_pps_context.first_idr = 1;
1890
1891
  return true;
1892
}
1893
1894
bool CCrystalHD::bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size)
1895
{
1896
  // based on h264_mp4toannexb_bsf.c (ffmpeg)
1897
  // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
1898
  // and Licensed GPL 2.1 or greater
1899
1900
  uint8_t *buf = pData;
1901
  uint32_t buf_size = iSize;
1902
  uint8_t  unit_type;
1903
  int32_t  nal_size;
1904
  uint32_t cumul_size = 0;
1905
  const uint8_t *buf_end = buf + buf_size;
1906
1907
  do
1908
  {
1909
    if (buf + m_sps_pps_context.length_size > buf_end)
1910
      goto fail;
1911
1912
    if (m_sps_pps_context.length_size == 1)
1913
      nal_size = buf[0];
1914
    else if (m_sps_pps_context.length_size == 2)
1915
      nal_size = buf[0] << 8 | buf[1];
1916
    else
1917
      nal_size = buf[0] << 24 | buf[1] << 16 | buf[2] << 8 | buf[3];
1918
1919
    buf += m_sps_pps_context.length_size;
1920
    unit_type = *buf & 0x1f;
1921
1922
    if (buf + nal_size > buf_end || nal_size < 0)
1923
      goto fail;
1924
1925
    // prepend only to the first type 5 NAL unit of an IDR picture
1926
    if (m_sps_pps_context.first_idr && unit_type == 5)
1927
    {
1928
      bitstream_alloc_and_copy(poutbuf, poutbuf_size,
1929
        m_sps_pps_context.sps_pps_data, m_sps_pps_context.size, buf, nal_size);
1930
      m_sps_pps_context.first_idr = 0;
1931
    }
1932
    else
1933
    {
1934
      bitstream_alloc_and_copy(poutbuf, poutbuf_size, NULL, 0, buf, nal_size);
1935
      if (!m_sps_pps_context.first_idr && unit_type == 1)
1936
          m_sps_pps_context.first_idr = 1;
1937
    }
1938
1939
    buf += nal_size;
1940
    cumul_size += nal_size + m_sps_pps_context.length_size;
1941
  } while (cumul_size < buf_size);
1942
1943
  return true;
1944
1945
fail:
1946
  free(*poutbuf);
1947
  *poutbuf = NULL;
1948
  *poutbuf_size = 0;
1949
  return false;
1950
}
1951
1952
void CCrystalHD::bitstream_alloc_and_copy(
1953
  uint8_t **poutbuf,      int *poutbuf_size,
1954
  const uint8_t *sps_pps, uint32_t sps_pps_size,
1955
  const uint8_t *in,      uint32_t in_size)
1956
{
1957
  // based on h264_mp4toannexb_bsf.c (ffmpeg)
1958
  // which is Copyright (c) 2007 Benoit Fouet <benoit.fouet@free.fr>
1959
  // and Licensed GPL 2.1 or greater
1960
1961
  #define CHD_WB32(p, d) { \
1962
    ((uint8_t*)(p))[3] = (d); \
1963
    ((uint8_t*)(p))[2] = (d) >> 8; \
1964
    ((uint8_t*)(p))[1] = (d) >> 16; \
1965
    ((uint8_t*)(p))[0] = (d) >> 24; }
1966
1967
  uint32_t offset = *poutbuf_size;
1968
  uint8_t nal_header_size = offset ? 3 : 4;
1969
1970
  *poutbuf_size += sps_pps_size + in_size + nal_header_size;
1971
  *poutbuf = (uint8_t*)realloc(*poutbuf, *poutbuf_size);
1972
  if (sps_pps)
1973
    memcpy(*poutbuf + offset, sps_pps, sps_pps_size);
1974
1975
  memcpy(*poutbuf + sps_pps_size + nal_header_size + offset, in, in_size);
1976
  if (!offset)
1977
  {
1978
    CHD_WB32(*poutbuf + sps_pps_size, 1);
1979
  }
1980
  else
1981
  {
1982
    (*poutbuf + offset + sps_pps_size)[0] = 0;
1983
    (*poutbuf + offset + sps_pps_size)[1] = 0;
1984
    (*poutbuf + offset + sps_pps_size)[2] = 1;
1985
  }
1986
}
1987
1988
////////////////////////////////////////////////////////////////////////////////////////////
1989
void PrintFormat(BCM::BC_PIC_INFO_BLOCK &pib)
1990
{
1991
  CLog::Log(LOGDEBUG, "----------------------------------\n%s","");
1992
  CLog::Log(LOGDEBUG, "\tTimeStamp: %" PRIu64"\n", pib.timeStamp);
1993
  CLog::Log(LOGDEBUG, "\tPicture Number: %d\n", pib.picture_number);
1994
  CLog::Log(LOGDEBUG, "\tWidth: %d\n", pib.width);
1995
  CLog::Log(LOGDEBUG, "\tHeight: %d\n", pib.height);
1996
  CLog::Log(LOGDEBUG, "\tChroma: 0x%03x\n", pib.chroma_format);
1997
  CLog::Log(LOGDEBUG, "\tPulldown: %d\n", pib.pulldown);
1998
  CLog::Log(LOGDEBUG, "\tFlags: 0x%08x\n", pib.flags);
1999
  CLog::Log(LOGDEBUG, "\tFrame Rate/Res: %d\n", pib.frame_rate);
2000
  CLog::Log(LOGDEBUG, "\tAspect Ratio: %d\n", pib.aspect_ratio);
2001
  CLog::Log(LOGDEBUG, "\tColor Primaries: %d\n", pib.colour_primaries);
2002
  CLog::Log(LOGDEBUG, "\tMetaData: %d\n", pib.picture_meta_payload);
2003
  CLog::Log(LOGDEBUG, "\tSession Number: %d\n", pib.sess_num);
2004
  CLog::Log(LOGDEBUG, "\tTimeStamp: %d\n", pib.ycom);
2005
  CLog::Log(LOGDEBUG, "\tCustom Aspect: %d\n", pib.custom_aspect_ratio_width_height);
2006
  CLog::Log(LOGDEBUG, "\tFrames to Drop: %d\n", pib.n_drop);
2007
  CLog::Log(LOGDEBUG, "\tH264 Valid Fields: 0x%08x\n", pib.other.h264.valid);
2008
}
2009
2010
#endif
(-)kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.h (+236 lines)
Line 0 Link Here
1
#pragma once
2
/*
3
 *      Copyright (C) 2005-2013 Team XBMC
4
 *      http://xbmc.org
5
 *
6
 *  This Program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2, or (at your option)
9
 *  any later version.
10
 *
11
 *  This Program is distributed in the hope that it will be useful,
12
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with XBMC; see the file COPYING.  If not, see
18
 *  <http://www.gnu.org/licenses/>.
19
 *
20
 */
21
22
#if defined(HAVE_LIBCRYSTALHD)
23
24
#include <deque>
25
26
#include "DVDVideoCodec.h"
27
#include "cores/dvdplayer/DVDStreamInfo.h"
28
#include "threads/SingleLock.h"
29
30
////////////////////////////////////////////////////////////////////////////////////////////
31
template <class T>
32
class CSyncPtrQueue
33
{
34
public:
35
  CSyncPtrQueue() { }
36
  virtual ~CSyncPtrQueue() { }
37
  void Push(T* p)
38
  {
39
    CSingleLock lock(m_Lock);
40
    m_Queue.push_back(p);
41
  }
42
43
  T* Pop()
44
  {
45
    T* p = NULL;
46
    CSingleLock lock(m_Lock);
47
    if (!m_Queue.empty())
48
    {
49
      p = m_Queue.front();
50
      m_Queue.pop_front();
51
    }
52
    return p;
53
  }
54
  unsigned int Count(){return m_Queue.size();}
55
protected:
56
  std::deque<T*> m_Queue;
57
  CCriticalSection m_Lock;
58
};
59
60
////////////////////////////////////////////////////////////////////////////////////////////
61
class CPictureBuffer
62
{
63
public:
64
  CPictureBuffer(ERenderFormat format, int width, int height);
65
  virtual ~CPictureBuffer();
66
67
  unsigned int  m_width;
68
  unsigned int  m_height;
69
  unsigned int  m_field;
70
  bool          m_interlace;
71
  double        m_framerate;
72
  uint64_t      m_timestamp;
73
  int           m_color_space;
74
  unsigned int  m_color_range;
75
  unsigned int  m_color_matrix;
76
  uint64_t      m_PictureNumber;
77
  ERenderFormat m_format;
78
  unsigned char *m_y_buffer_ptr;
79
  unsigned char *m_u_buffer_ptr;
80
  unsigned char *m_v_buffer_ptr;
81
  unsigned char *m_uv_buffer_ptr;
82
  int           m_y_buffer_size;
83
  int           m_u_buffer_size;
84
  int           m_v_buffer_size;
85
  int           m_uv_buffer_size;
86
};
87
88
89
////////////////////////////////////////////////////////////////////////////////////////////
90
enum _CRYSTALHD_CODEC_TYPES
91
{
92
  CRYSTALHD_CODEC_ID_MPEG2 = 0,
93
  CRYSTALHD_CODEC_ID_H264  = 1,
94
  CRYSTALHD_CODEC_ID_AVC1  = 2,
95
  CRYSTALHD_CODEC_ID_VC1   = 3,
96
  CRYSTALHD_CODEC_ID_WMV3  = 4,
97
  CRYSTALHD_CODEC_ID_WVC1  = 5,
98
};
99
100
typedef uint32_t CRYSTALHD_CODEC_TYPE;
101
102
#if (HAVE_LIBCRYSTALHD == 2)
103
104
  typedef struct _BC_INFO_CRYSTAL_ {
105
	  uint8_t device;
106
	  union {
107
		  struct {
108
			  uint32_t dilRelease:8;
109
			  uint32_t dilMajor:8;
110
			  uint32_t dilMinor:16;
111
		  };
112
		  uint32_t version;
113
	  } dilVersion;
114
115
	  union {
116
		  struct {
117
			  uint32_t drvRelease:4;
118
			  uint32_t drvMajor:8;
119
			  uint32_t drvMinor:12;
120
			  uint32_t drvBuild:8;
121
		  };
122
		  uint32_t version;
123
	  } drvVersion;
124
125
	  union {
126
		  struct {
127
			  uint32_t fwRelease:4;
128
			  uint32_t fwMajor:8;
129
			  uint32_t fwMinor:12;
130
			  uint32_t fwBuild:8;
131
		  };
132
		  uint32_t version;
133
	  } fwVersion;
134
135
	  uint32_t Reserved1; // For future expansion
136
	  uint32_t Reserved2; // For future expansion
137
  } BC_INFO_CRYSTAL, *PBC_INFO_CRYSTAL;
138
139
#endif
140
141
////////////////////////////////////////////////////////////////////////////////////////////
142
143
#define CRYSTALHD_FIELD_FULL        0x00
144
#define CRYSTALHD_FIELD_BOT         0x01
145
#define CRYSTALHD_FIELD_TOP         0x02
146
147
typedef struct CHD_CODEC_PARAMS {
148
  uint8_t   *sps_pps_buf;
149
  uint32_t  sps_pps_size;
150
  uint8_t   nal_size_bytes;
151
} CHD_CODEC_PARAMS;
152
153
class DllLibCrystalHD;
154
class CMPCInputThread;
155
class CMPCOutputThread;
156
157
class CCrystalHD
158
{
159
public:
160
  virtual ~CCrystalHD();
161
162
  static void RemoveInstance(void);
163
  static CCrystalHD* GetInstance(void);
164
165
  bool DevicePresent(void);
166
167
  void OpenDevice();
168
  void CloseDevice();
169
170
  bool OpenDecoder(CRYSTALHD_CODEC_TYPE codec_type, CDVDStreamInfo &hints);
171
  void CloseDecoder(void);
172
  void Reset(void);
173
174
  bool AddInput(unsigned char *pData, size_t size, double dts, double pts);
175
176
  int  GetReadyCount(void);
177
  void BusyListFlush(void);
178
179
  bool GetPicture(DVDVideoPicture* pDvdVideoPicture);
180
  void SetDropState(bool bDrop);
181
182
protected:
183
184
  DllLibCrystalHD *m_dll;
185
  void          *m_device;
186
  bool          m_device_preset;
187
  bool          m_new_lib;
188
  bool          m_decoder_open;
189
  bool          m_has_bcm70015;
190
  int           m_color_space;
191
  bool          m_drop_state;
192
  bool          m_skip_state;
193
  unsigned int  m_timeout;
194
  unsigned int  m_wait_timeout;
195
  unsigned int  m_field;
196
  unsigned int  m_width;
197
  unsigned int  m_height;
198
  int           m_reset;
199
  int           m_last_pict_num;
200
  double        m_last_demuxer_pts;
201
  double        m_last_decoder_pts;
202
203
  CMPCOutputThread *m_pOutputThread;
204
  CSyncPtrQueue<CPictureBuffer> m_BusyList;
205
#if (HAVE_LIBCRYSTALHD == 2)
206
  BC_INFO_CRYSTAL m_bc_info_crystal;
207
#endif
208
209
private:
210
  CCrystalHD();
211
  CCrystalHD(const CCrystalHD& other);
212
  CCrystalHD& operator=(const CCrystalHD&);
213
  static CCrystalHD *m_pInstance;
214
215
  // bitstream to bytestream (Annex B) conversion support.
216
  bool bitstream_convert_init(void *in_extradata, int in_extrasize);
217
  bool bitstream_convert(uint8_t* pData, int iSize, uint8_t **poutbuf, int *poutbuf_size);
218
  static void bitstream_alloc_and_copy( uint8_t **poutbuf, int *poutbuf_size,
219
    const uint8_t *sps_pps, uint32_t sps_pps_size, const uint8_t *in, uint32_t in_size);
220
221
  typedef struct chd_bitstream_ctx {
222
      uint8_t  length_size;
223
      uint8_t  first_idr;
224
      uint8_t *sps_pps_data;
225
      uint32_t size;
226
  } chd_bitstream_ctx;
227
228
  uint32_t          m_sps_pps_size;
229
  chd_bitstream_ctx m_sps_pps_context;
230
  bool              m_convert_bitstream;
231
232
  bool extract_sps_pps_from_avcc(int extradata_size, void *extradata);
233
  CHD_CODEC_PARAMS  m_chd_params;
234
};
235
236
#endif
(-)kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.cpp (+204 lines)
Line 0 Link Here
1
/*
2
 *      Copyright (C) 2005-2013 Team XBMC
3
 *      http://xbmc.org
4
 *
5
 *  This Program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2, or (at your option)
8
 *  any later version.
9
 *
10
 *  This Program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with XBMC; see the file COPYING.  If not, see
17
 *  <http://www.gnu.org/licenses/>.
18
 *
19
 */
20
21
#if (defined HAVE_CONFIG_H) && (!defined TARGET_WINDOWS)
22
  #include "config.h"
23
#elif defined(TARGET_WINDOWS)
24
#include "system.h"
25
extern "C" {
26
#include "libavcodec/avcodec.h"
27
}
28
#endif
29
30
#if defined(HAVE_LIBCRYSTALHD)
31
#include "DVDClock.h"
32
#include "DVDStreamInfo.h"
33
#include "DVDVideoCodecCrystalHD.h"
34
#include "settings/Settings.h"
35
#include "utils/log.h"
36
#include "utils/TimeUtils.h"
37
38
#define __MODULE_NAME__ "DVDVideoCodecCrystalHD"
39
40
CDVDVideoCodecCrystalHD::CDVDVideoCodecCrystalHD() :
41
  m_Codec(NULL),
42
  m_DropPictures(false),
43
  m_Duration(0.0),
44
  m_pFormatName(""),
45
  m_CodecType(CRYSTALHD_CODEC_ID_MPEG2)
46
{
47
}
48
49
CDVDVideoCodecCrystalHD::~CDVDVideoCodecCrystalHD()
50
{
51
  Dispose();
52
}
53
54
bool CDVDVideoCodecCrystalHD::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
55
{
56
  if (CSettings::Get().GetBool("videoplayer.usechd") && !hints.software)
57
  {
58
    switch (hints.codec)
59
    {
60
      case AV_CODEC_ID_MPEG2VIDEO:
61
        m_CodecType = CRYSTALHD_CODEC_ID_MPEG2;
62
        m_pFormatName = "chd-mpeg2";
63
      break;
64
      case AV_CODEC_ID_H264:
65
        switch(hints.profile)
66
        {
67
          case FF_PROFILE_H264_HIGH_10:
68
          case FF_PROFILE_H264_HIGH_10_INTRA:
69
          case FF_PROFILE_H264_HIGH_422:
70
          case FF_PROFILE_H264_HIGH_422_INTRA:
71
          case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
72
          case FF_PROFILE_H264_HIGH_444_INTRA:
73
          case FF_PROFILE_H264_CAVLC_444:
74
            CLog::Log(LOGNOTICE, "%s - unsupported h264 profile(%d)", __FUNCTION__, hints.profile);
75
            return false;
76
            break;
77
        }
78
        if (hints.extrasize < 7 || hints.extradata == NULL)
79
        {
80
          CLog::Log(LOGNOTICE, "%s - avcC atom too data small or missing", __FUNCTION__);
81
          return false;
82
        }
83
        // valid avcC data (bitstream) always starts with the value 1 (version)
84
        if ( *(char*)hints.extradata == 1 )
85
          m_CodecType = CRYSTALHD_CODEC_ID_AVC1;
86
        else
87
          m_CodecType = CRYSTALHD_CODEC_ID_H264;
88
89
        m_pFormatName = "chd-h264";
90
      break;
91
      case AV_CODEC_ID_VC1:
92
        m_CodecType = CRYSTALHD_CODEC_ID_VC1;
93
        m_pFormatName = "chd-vc1";
94
      break;
95
      case AV_CODEC_ID_WMV3:
96
        m_CodecType = CRYSTALHD_CODEC_ID_WMV3;
97
        m_pFormatName = "chd-wmv3";
98
      break;
99
      default:
100
        return false;
101
      break;
102
    }
103
104
    m_Codec = CCrystalHD::GetInstance();
105
    if (!m_Codec)
106
    {
107
      CLog::Log(LOGERROR, "%s: Failed to open Broadcom Crystal HD Codec", __MODULE_NAME__);
108
      return false;
109
    }
110
111
    if (m_Codec && !m_Codec->OpenDecoder(m_CodecType, hints))
112
    {
113
      CLog::Log(LOGERROR, "%s: Failed to open Broadcom Crystal HD Codec", __MODULE_NAME__);
114
      return false;
115
    }
116
117
    // default duration to 23.976 fps, have to guess something.
118
    m_Duration = (DVD_TIME_BASE / (24.0 * 1000.0/1001.0));
119
    m_DropPictures = false;
120
121
    CLog::Log(LOGINFO, "%s: Opened Broadcom Crystal HD Codec", __MODULE_NAME__);
122
    return true;
123
  }
124
125
  return false;
126
}
127
128
void CDVDVideoCodecCrystalHD::Dispose(void)
129
{
130
  if (m_Codec)
131
  {
132
    m_Codec->CloseDecoder();
133
    m_Codec = NULL;
134
  }
135
}
136
137
int CDVDVideoCodecCrystalHD::Decode(uint8_t *pData, int iSize, double dts, double pts)
138
{
139
  if (!pData)
140
  {
141
    // if pData is nil, we are in dvdplayervideo's special loop
142
    // where it checks for more picture frames, you must pass
143
    // VC_BUFFER to get it to break out of this loop.
144
    int ready_cnt = m_Codec->GetReadyCount();
145
    if (ready_cnt == 1)
146
      return VC_PICTURE | VC_BUFFER;
147
    if (ready_cnt > 2)
148
      return VC_PICTURE;
149
    else
150
      return VC_BUFFER;
151
  }
152
153
  // We are running a picture queue, picture frames are allocated
154
  // in CrystalHD class if needed, then passed up. Need to return
155
  // them back to CrystalHD class for re-queuing. This way we keep
156
  // the memory alloc/free to a minimum and don't churn memory for
157
  // each picture frame.
158
  m_Codec->BusyListFlush();
159
160
  if (pData)
161
  {
162
    // Handle Input, add demuxer packet to input queue, we must accept it or
163
    // it will be discarded as DVDPlayerVideo has no concept of "try again".
164
    if ( !m_Codec->AddInput(pData, iSize, dts, pts) )
165
    {
166
      // Deep crap error, this should never happen unless we run away pulling demuxer pkts.
167
      CLog::Log(LOGDEBUG, "%s: m_pInputThread->AddInput full.", __MODULE_NAME__);
168
      Sleep(10);
169
    }
170
  }
171
172
  // if we have more than one frame ready, just return VC_PICTURE so 
173
  // dvdplayervideo will loop and drain them before sending another demuxer packet.
174
  if (m_Codec->GetReadyCount() > 2)
175
    return VC_PICTURE;
176
  
177
  int rtn = 0;
178
  if (m_Codec->GetReadyCount())
179
    rtn = VC_PICTURE;
180
181
  return rtn | VC_BUFFER;
182
}
183
184
void CDVDVideoCodecCrystalHD::Reset(void)
185
{
186
  m_Codec->Reset();
187
}
188
189
bool CDVDVideoCodecCrystalHD::GetPicture(DVDVideoPicture* pDvdVideoPicture)
190
{
191
  bool  ret;
192
  
193
  ret = m_Codec->GetPicture(pDvdVideoPicture);
194
  m_Duration = pDvdVideoPicture->iDuration;
195
  return ret;
196
}
197
198
void CDVDVideoCodecCrystalHD::SetDropState(bool bDrop)
199
{
200
  m_DropPictures = bDrop;
201
  m_Codec->SetDropState(m_DropPictures);
202
}
203
204
#endif
(-)kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecCrystalHD.h (+51 lines)
Line 0 Link Here
1
/*
2
 *      Copyright (C) 2005-2013 Team XBMC
3
 *      http://xbmc.org
4
 *
5
 *  This Program is free software; you can redistribute it and/or modify
6
 *  it under the terms of the GNU General Public License as published by
7
 *  the Free Software Foundation; either version 2, or (at your option)
8
 *  any later version.
9
 *
10
 *  This Program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with XBMC; see the file COPYING.  If not, see
17
 *  <http://www.gnu.org/licenses/>.
18
 *
19
 */
20
21
#pragma once
22
23
#if defined(HAVE_LIBCRYSTALHD)
24
25
#include "CrystalHD.h"
26
#include "DVDVideoCodec.h"
27
28
class CDVDVideoCodecCrystalHD : public CDVDVideoCodec
29
{
30
public:
31
  CDVDVideoCodecCrystalHD();
32
  virtual ~CDVDVideoCodecCrystalHD();
33
34
  // Required overrides
35
  virtual bool Open(CDVDStreamInfo &hints, CDVDCodecOptions &options);
36
  virtual void Dispose(void);
37
  virtual int  Decode(uint8_t *pData, int iSize, double dts, double pts);
38
  virtual void Reset(void);
39
  virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
40
  virtual void SetDropState(bool bDrop);
41
  virtual const char* GetName(void) { return (const char*)m_pFormatName; }
42
43
protected:
44
  CCrystalHD      *m_Codec;
45
  bool            m_DropPictures;
46
  double          m_Duration;
47
  const char      *m_pFormatName;
48
  CRYSTALHD_CODEC_TYPE m_CodecType;
49
};
50
51
#endif
(-)kodi-15.1~/xbmc/cores/dvdplayer/DVDCodecs/Video/Makefile.in (+4 lines)
Lines 11-16 endif Link Here
11
ifeq (@USE_VAAPI@,1)
11
ifeq (@USE_VAAPI@,1)
12
SRCS += VAAPI.cpp
12
SRCS += VAAPI.cpp
13
endif
13
endif
14
ifeq (@USE_CRYSTALHD@,1)
15
SRCS += CrystalHD.cpp
16
SRCS += DVDVideoCodecCrystalHD.cpp
17
endif
14
ifeq ($(findstring osx,@ARCH@),osx)
18
ifeq ($(findstring osx,@ARCH@),osx)
15
SRCS += DVDVideoCodecVDA.cpp
19
SRCS += DVDVideoCodecVDA.cpp
16
SRCS += VDA.cpp
20
SRCS += VDA.cpp
(-)kodi-15.1~/xbmc/DllPaths_generated.h.in (+7 lines)
Lines 46-51 Link Here
46
#define DLL_PATH_LIBDVDNAV     "special://xbmcbin/system/players/dvdplayer/libdvdnav-@ARCH@.so"
46
#define DLL_PATH_LIBDVDNAV     "special://xbmcbin/system/players/dvdplayer/libdvdnav-@ARCH@.so"
47
#define DLL_PATH_LIBMPEG2      "@MPEG2_SONAME@"
47
#define DLL_PATH_LIBMPEG2      "@MPEG2_SONAME@"
48
48
49
/* broadcom crystalhd */
50
#if defined(TARGET_DARWIN)
51
#define DLL_PATH_LIBCRYSTALHD  "libcrystalhd.dylib"
52
#else
53
#define DLL_PATH_LIBCRYSTALHD  "@CRYSTALHD_SONAME@"
54
#endif
55
49
/* libbluray */
56
/* libbluray */
50
#define DLL_PATH_LIBBLURAY     "@BLURAY_SONAME@"
57
#define DLL_PATH_LIBBLURAY     "@BLURAY_SONAME@"
51
58
(-)kodi-15.1~/xbmc/settings/SettingConditions.cpp (+8 lines)
Lines 29-34 Link Here
29
#include "android/activity/AndroidFeatures.h"
29
#include "android/activity/AndroidFeatures.h"
30
#endif // defined(TARGET_ANDROID)
30
#endif // defined(TARGET_ANDROID)
31
#include "cores/AudioEngine/AEFactory.h"
31
#include "cores/AudioEngine/AEFactory.h"
32
#if defined(HAVE_LIBCRYSTALHD)
33
#include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h"
34
#endif // defined(HAVE_LIBCRYSTALHD)
32
#include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h"
35
#include "cores/dvdplayer/DVDCodecs/Video/DVDVideoCodec.h"
33
#include "guilib/LocalizeStrings.h"
36
#include "guilib/LocalizeStrings.h"
34
#include "peripherals/Peripherals.h"
37
#include "peripherals/Peripherals.h"
Lines 224-229 void CSettingConditions::Initialize() Link Here
224
#ifdef HAS_ZEROCONF
227
#ifdef HAS_ZEROCONF
225
  m_simpleConditions.insert("has_zeroconf");
228
  m_simpleConditions.insert("has_zeroconf");
226
#endif
229
#endif
230
#ifdef HAVE_LIBCRYSTALHD
231
  m_simpleConditions.insert("have_libcrystalhd");
232
  if (CCrystalHD::GetInstance()->DevicePresent())
233
    m_simpleConditions.insert("hascrystalhddevice");
234
#endif
227
#ifdef HAVE_LIBOPENMAX
235
#ifdef HAVE_LIBOPENMAX
228
  m_simpleConditions.insert("have_libopenmax");
236
  m_simpleConditions.insert("have_libopenmax");
229
#endif
237
#endif
(-)kodi-15.1~/xbmc/system.h (+1 lines)
Lines 106-111 Link Here
106
#define HAS_WIN32_NETWORK
106
#define HAS_WIN32_NETWORK
107
#define HAS_IRSERVERSUITE
107
#define HAS_IRSERVERSUITE
108
#define HAS_AUDIO
108
#define HAS_AUDIO
109
#define HAVE_LIBCRYSTALHD 2
109
#define HAS_WEB_SERVER
110
#define HAS_WEB_SERVER
110
#define HAS_WEB_INTERFACE
111
#define HAS_WEB_INTERFACE
111
#define HAVE_LIBSSH
112
#define HAVE_LIBSSH

Return to bug 30920