2 * Copyright (C) 2005-2008 Team XBMC
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)
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.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, write to
17 * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18 * http://www.gnu.org/copyleft/gpl.html
22 #include "DVDCodecUtils.h"
23 #include "cores/VideoRenderers/RenderManager.h"
24 #include "utils/log.h"
25 #include "utils/fastmemcpy.h"
26 #include "../Codecs/DllSwScale.h"
27 #include "../Codecs/DllAvCodec.h"
29 // allocate a new picture (PIX_FMT_YUV420P)
30 DVDVideoPicture* CDVDCodecUtils::AllocatePicture(int iWidth, int iHeight)
32 DVDVideoPicture* pPicture = new DVDVideoPicture;
35 pPicture->iWidth = iWidth;
36 pPicture->iHeight = iHeight;
41 int totalsize = (iWidth * iHeight) + size * 2;
42 BYTE* data = new BYTE[totalsize];
45 pPicture->data[0] = data;
46 pPicture->data[1] = pPicture->data[0] + (iWidth * iHeight);
47 pPicture->data[2] = pPicture->data[1] + size;
48 pPicture->data[3] = NULL;
49 pPicture->iLineSize[0] = iWidth;
50 pPicture->iLineSize[1] = w;
51 pPicture->iLineSize[2] = w;
52 pPicture->iLineSize[3] = 0;
56 CLog::Log(LOGFATAL, "CDVDCodecUtils::AllocatePicture, unable to allocate new video picture, out of memory.");
64 void CDVDCodecUtils::FreePicture(DVDVideoPicture* pPicture)
66 delete[] pPicture->data[0];
70 bool CDVDCodecUtils::CopyPicture(DVDVideoPicture* pDst, DVDVideoPicture* pSrc)
74 int h = pSrc->iHeight;
79 for (int y = 0; y < h; y++)
82 s += pSrc->iLineSize[0];
83 d += pDst->iLineSize[0];
91 for (int y = 0; y < h; y++)
94 s += pSrc->iLineSize[1];
95 d += pDst->iLineSize[1];
100 for (int y = 0; y < h; y++)
102 fast_memcpy(d, s, w);
103 s += pSrc->iLineSize[2];
104 d += pDst->iLineSize[2];
109 bool CDVDCodecUtils::CopyPicture(YV12Image* pImage, DVDVideoPicture *pSrc)
111 BYTE *s = pSrc->data[0];
112 BYTE *d = pImage->plane[0];
113 int w = pSrc->iWidth;
114 int h = pSrc->iHeight;
115 if ((w == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0]))
117 fast_memcpy(d, s, w*h);
121 for (int y = 0; y < h; y++)
123 fast_memcpy(d, s, w);
124 s += pSrc->iLineSize[0];
125 d += pImage->stride[0];
129 d = pImage->plane[1];
130 w = pSrc->iWidth >> 1;
131 h = pSrc->iHeight >> 1;
132 if ((w==pSrc->iLineSize[1]) && ((unsigned int) pSrc->iLineSize[1]==pImage->stride[1]))
134 fast_memcpy(d, s, w*h);
138 for (int y = 0; y < h; y++)
140 fast_memcpy(d, s, w);
141 s += pSrc->iLineSize[1];
142 d += pImage->stride[1];
146 d = pImage->plane[2];
147 if ((w==pSrc->iLineSize[2]) && ((unsigned int) pSrc->iLineSize[2]==pImage->stride[2]))
149 fast_memcpy(d, s, w*h);
153 for (int y = 0; y < h; y++)
155 fast_memcpy(d, s, w);
156 s += pSrc->iLineSize[2];
157 d += pImage->stride[2];
163 DVDVideoPicture* CDVDCodecUtils::ConvertToNV12Picture(DVDVideoPicture *pSrc)
165 // Clone a YV12 picture to new NV12 picture.
166 DVDVideoPicture* pPicture = new DVDVideoPicture;
171 int w = pPicture->iWidth / 2;
172 int h = pPicture->iHeight / 2;
174 int totalsize = (pPicture->iWidth * pPicture->iHeight) + size * 2;
175 BYTE* data = new BYTE[totalsize];
178 pPicture->data[0] = data;
179 pPicture->data[1] = pPicture->data[0] + (pPicture->iWidth * pPicture->iHeight);
180 pPicture->data[2] = NULL;
181 pPicture->data[3] = NULL;
182 pPicture->iLineSize[0] = pPicture->iWidth;
183 pPicture->iLineSize[1] = pPicture->iWidth;
184 pPicture->iLineSize[2] = 0;
185 pPicture->iLineSize[3] = 0;
186 pPicture->format = DVDVideoPicture::FMT_NV12;
189 uint8_t *s = pSrc->data[0];
190 uint8_t *d = pPicture->data[0];
191 for (int y = 0; y < (int)pSrc->iHeight; y++)
193 fast_memcpy(d, s, pSrc->iWidth);
194 s += pSrc->iLineSize[0];
195 d += pPicture->iLineSize[0];
199 uint8_t *s_u, *s_v, *d_uv;
200 for (int y = 0; y < (int)pSrc->iHeight/2; y++) {
201 s_u = pSrc->data[1] + (y * pSrc->iLineSize[1]);
202 s_v = pSrc->data[2] + (y * pSrc->iLineSize[2]);
203 d_uv = pPicture->data[1] + (y * pPicture->iLineSize[1]);
204 for (int x = 0; x < (int)pSrc->iWidth/2; x++) {
213 CLog::Log(LOGFATAL, "CDVDCodecUtils::AllocateNV12Picture, unable to allocate new video picture, out of memory.");
221 DVDVideoPicture* CDVDCodecUtils::ConvertToYUV422PackedPicture(DVDVideoPicture *pSrc, DVDVideoPicture::EFormat format)
223 // Clone a YV12 picture to new YUY2 or UYVY picture.
224 DVDVideoPicture* pPicture = new DVDVideoPicture;
229 int totalsize = pPicture->iWidth * pPicture->iHeight * 2;
230 BYTE* data = new BYTE[totalsize];
234 pPicture->data[0] = data;
235 pPicture->data[1] = NULL;
236 pPicture->data[2] = NULL;
237 pPicture->data[3] = NULL;
238 pPicture->iLineSize[0] = pPicture->iWidth * 2;
239 pPicture->iLineSize[1] = 0;
240 pPicture->iLineSize[2] = 0;
241 pPicture->iLineSize[3] = 0;
242 pPicture->format = format;
244 //if this is going to be used for anything else than testing the renderer
245 //the libraries should not be loaded on every function call
247 DllAvCodec dllAvCodec;
248 DllSwScale dllSwScale;
249 if (!dllAvUtil.Load() || !dllAvCodec.Load() || !dllSwScale.Load())
251 CLog::Log(LOGERROR,"CDVDCodecUtils::ConvertToYUY2Picture - failed to load rescale libraries!");
255 // Perform the scaling.
256 uint8_t* src[] = { pSrc->data[0], pSrc->data[1], pSrc->data[2], NULL };
257 int srcStride[] = { pSrc->iLineSize[0], pSrc->iLineSize[1], pSrc->iLineSize[2], NULL };
258 uint8_t* dst[] = { pPicture->data[0], NULL, NULL, NULL };
259 int dstStride[] = { pPicture->iLineSize[0], NULL, NULL, NULL };
262 if (format == DVDVideoPicture::FMT_UYVY)
263 dstformat = PIX_FMT_UYVY422;
265 dstformat = PIX_FMT_YUYV422;
267 struct SwsContext *ctx = dllSwScale.sws_getContext(pSrc->iWidth, pSrc->iHeight, PIX_FMT_YUV420P,
268 pPicture->iWidth, pPicture->iHeight, dstformat,
269 SWS_FAST_BILINEAR | SwScaleCPUFlags(),
271 dllSwScale.sws_scale(ctx, src, srcStride, 0, pSrc->iHeight, dst, dstStride);
272 dllSwScale.sws_freeContext(ctx);
277 CLog::Log(LOGFATAL, "CDVDCodecUtils::ConvertToYUY2Picture, unable to allocate new video picture, out of memory.");
285 bool CDVDCodecUtils::CopyNV12Picture(YV12Image* pImage, DVDVideoPicture *pSrc)
287 BYTE *s = pSrc->data[0];
288 BYTE *d = pImage->plane[0];
289 int w = pSrc->iWidth;
290 int h = pSrc->iHeight;
292 if ((w == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0]))
294 fast_memcpy(d, s, w*h);
298 for (int y = 0; y < h; y++)
300 fast_memcpy(d, s, w);
301 s += pSrc->iLineSize[0];
302 d += pImage->stride[0];
307 d = pImage->plane[1];
309 h = pSrc->iHeight >> 1;
310 // Copy packed UV (width is same as for Y as it's both U and V components)
311 if ((w==pSrc->iLineSize[1]) && ((unsigned int) pSrc->iLineSize[1]==pImage->stride[1]))
313 fast_memcpy(d, s, w*h);
317 for (int y = 0; y < h; y++)
319 fast_memcpy(d, s, w);
320 s += pSrc->iLineSize[1];
321 d += pImage->stride[1];
328 bool CDVDCodecUtils::CopyYUV422PackedPicture(YV12Image* pImage, DVDVideoPicture *pSrc)
330 BYTE *s = pSrc->data[0];
331 BYTE *d = pImage->plane[0];
332 int w = pSrc->iWidth;
333 int h = pSrc->iHeight;
336 if ((w * 2 == pSrc->iLineSize[0]) && ((unsigned int) pSrc->iLineSize[0] == pImage->stride[0]))
338 fast_memcpy(d, s, w*h*2);
342 for (int y = 0; y < h; y++)
344 fast_memcpy(d, s, w*2);
345 s += pSrc->iLineSize[0];
346 d += pImage->stride[0];