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

http://github.com/xbmc/xbmc · C++ · 214 lines · 157 code · 36 blank · 21 comment · 39 complexity · 95b615065ad56304380f577e9b065c53 MD5 · raw file

  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 "DVDVideoPPFFmpeg.h"
  21. #include "utils/log.h"
  22. CDVDVideoPPFFmpeg::CDVDVideoPPFFmpeg(const CStdString& mType)
  23. {
  24. m_sType = mType;
  25. m_pMode = m_pContext = NULL;
  26. m_pSource = m_pTarget = NULL;
  27. m_iInitWidth = m_iInitHeight = 0;
  28. m_deinterlace = false;
  29. memset(&m_FrameBuffer, 0, sizeof(DVDVideoPicture));
  30. }
  31. CDVDVideoPPFFmpeg::~CDVDVideoPPFFmpeg()
  32. {
  33. Dispose();
  34. }
  35. void CDVDVideoPPFFmpeg::Dispose()
  36. {
  37. if (m_pMode)
  38. {
  39. m_dll.pp_free_mode(m_pMode);
  40. m_pMode = NULL;
  41. }
  42. if(m_pContext)
  43. {
  44. m_dll.pp_free_context(m_pContext);
  45. m_pContext = NULL;
  46. }
  47. if( m_FrameBuffer.iFlags & DVP_FLAG_ALLOCATED )
  48. {
  49. for( int i = 0; i<4; i++ )
  50. {
  51. if( m_FrameBuffer.data[i] )
  52. {
  53. _aligned_free(m_FrameBuffer.data[i]);
  54. m_FrameBuffer.data[i] = NULL;
  55. m_FrameBuffer.iLineSize[i] = 0;
  56. }
  57. }
  58. m_FrameBuffer.iFlags &= ~DVP_FLAG_ALLOCATED;
  59. }
  60. m_iInitWidth = 0;
  61. m_iInitHeight = 0;
  62. m_dll.Unload();
  63. }
  64. bool CDVDVideoPPFFmpeg::CheckInit(int iWidth, int iHeight)
  65. {
  66. if (!m_dll.IsLoaded() && !m_dll.Load()) return false;
  67. if(m_iInitWidth != iWidth || m_iInitHeight != iHeight)
  68. {
  69. if(m_pContext || m_pMode)
  70. {
  71. Dispose();
  72. }
  73. m_pContext = m_dll.pp_get_context(m_pSource->iWidth, m_pSource->iHeight, PPCPUFlags() | PP_FORMAT_420);
  74. m_iInitWidth = m_pSource->iWidth;
  75. m_iInitHeight = m_pSource->iHeight;
  76. m_pMode = m_dll.pp_get_mode_by_name_and_quality((char *)m_sType.c_str(), PP_QUALITY_MAX);
  77. }
  78. if(m_pMode)
  79. return true;
  80. else
  81. return false;
  82. }
  83. void CDVDVideoPPFFmpeg::SetType(const CStdString& mType, bool deinterlace)
  84. {
  85. m_deinterlace = deinterlace;
  86. if (mType == m_sType)
  87. return;
  88. m_sType = mType;
  89. if(m_pContext || m_pMode)
  90. Dispose();
  91. }
  92. bool CDVDVideoPPFFmpeg::Process(DVDVideoPicture* pPicture)
  93. {
  94. m_pSource = pPicture;
  95. if(m_pSource->format != RENDER_FMT_YUV420P)
  96. return false;
  97. if( !CheckInit(m_pSource->iWidth, m_pSource->iHeight) )
  98. {
  99. CLog::Log(LOGERROR, "Initialization of ffmpeg postprocessing failed");
  100. return false;
  101. }
  102. //If no target was set or we are using internal buffer, make sure it's correctly sized
  103. if(m_pTarget == &m_FrameBuffer || !m_pTarget)
  104. {
  105. if(CheckFrameBuffer(m_pSource))
  106. m_pTarget = &m_FrameBuffer;
  107. else
  108. {
  109. m_pTarget = NULL;
  110. return false;
  111. }
  112. }
  113. int pict_type = (m_pSource->qscale_type != DVP_QSCALE_MPEG1) ?
  114. PP_PICT_TYPE_QP2 : 0;
  115. m_dll.pp_postprocess(m_pSource->data, m_pSource->iLineSize,
  116. m_pTarget->data, m_pTarget->iLineSize,
  117. m_pSource->iWidth, m_pSource->iHeight,
  118. m_pSource->qscale_table, m_pSource->qscale_stride,
  119. m_pMode, m_pContext,
  120. pict_type); //m_pSource->iFrameType);
  121. //Copy frame information over to target, but make sure it is set as allocated should decoder have forgotten
  122. m_pTarget->iFlags = m_pSource->iFlags | DVP_FLAG_ALLOCATED;
  123. if (m_deinterlace)
  124. m_pTarget->iFlags &= ~DVP_FLAG_INTERLACED;
  125. m_pTarget->iFrameType = m_pSource->iFrameType;
  126. m_pTarget->iRepeatPicture = m_pSource->iRepeatPicture;;
  127. m_pTarget->iDuration = m_pSource->iDuration;
  128. m_pTarget->qscale_table = m_pSource->qscale_table;
  129. m_pTarget->qscale_stride = m_pSource->qscale_stride;
  130. m_pTarget->qscale_type = m_pSource->qscale_type;
  131. m_pTarget->iDisplayHeight = m_pSource->iDisplayHeight;
  132. m_pTarget->iDisplayWidth = m_pSource->iDisplayWidth;
  133. m_pTarget->pts = m_pSource->pts;
  134. m_pTarget->format = RENDER_FMT_YUV420P;
  135. return true;
  136. }
  137. bool CDVDVideoPPFFmpeg::CheckFrameBuffer(const DVDVideoPicture* pSource)
  138. {
  139. if( m_FrameBuffer.iFlags & DVP_FLAG_ALLOCATED && (m_FrameBuffer.iWidth != pSource->iWidth || m_FrameBuffer.iHeight != pSource->iHeight))
  140. {
  141. m_FrameBuffer.iFlags &= ~DVP_FLAG_ALLOCATED;
  142. for(int i = 0;i<3;i++)
  143. if(m_FrameBuffer.data[i])
  144. {
  145. delete[] m_FrameBuffer.data[i];
  146. m_FrameBuffer.data[i] = NULL;
  147. }
  148. }
  149. if(!(m_FrameBuffer.iFlags & DVP_FLAG_ALLOCATED))
  150. {
  151. memset(&m_FrameBuffer, 0, sizeof(DVDVideoPicture));
  152. m_FrameBuffer.iLineSize[0] = pSource->iLineSize[0]; //Y
  153. m_FrameBuffer.iLineSize[1] = pSource->iLineSize[1]; //U
  154. m_FrameBuffer.iLineSize[2] = pSource->iLineSize[2]; //V
  155. m_FrameBuffer.iLineSize[3] = 0;
  156. m_FrameBuffer.iWidth = pSource->iWidth;
  157. m_FrameBuffer.iHeight = pSource->iHeight;
  158. m_FrameBuffer.data[0] = (uint8_t*)_aligned_malloc(m_FrameBuffer.iLineSize[0] * m_FrameBuffer.iHeight , 16);
  159. m_FrameBuffer.data[1] = (uint8_t*)_aligned_malloc(m_FrameBuffer.iLineSize[1] * m_FrameBuffer.iHeight/2, 16);
  160. m_FrameBuffer.data[2] = (uint8_t*)_aligned_malloc(m_FrameBuffer.iLineSize[2] * m_FrameBuffer.iHeight/2, 16);
  161. if( !m_FrameBuffer.data[0] || !m_FrameBuffer.data[1] || !m_FrameBuffer.data[2])
  162. {
  163. CLog::Log(LOGERROR, "CDVDVideoDeinterlace::AllocBufferOfType - Unable to allocate framebuffer, bailing");
  164. return false;
  165. }
  166. m_FrameBuffer.iFlags |= DVP_FLAG_ALLOCATED;
  167. }
  168. return true;
  169. }
  170. bool CDVDVideoPPFFmpeg::GetPicture(DVDVideoPicture* pPicture)
  171. {
  172. if( m_pTarget )
  173. {
  174. memmove(pPicture, m_pTarget, sizeof(DVDVideoPicture));
  175. return true;
  176. }
  177. return false;
  178. }