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

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

Return to bug 30920