PageRenderTime 60ms CodeModel.GetById 23ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 0ms

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