PageRenderTime 56ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/xbmc/cores/dvdplayer/DVDCodecs/Video/CrystalHD.cpp

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