Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

[osx] refactor vda to pass cvbufrefs up for rendering, decreases CPU …

…from 55 to 35 percent when decoding 1080p via vda
  • Loading branch information...
commit 1e941981510f28bee9012b4278ce48ab026a433b 1 parent eac347e
@davilla authored
View
211 xbmc/cores/VideoRenderers/LinuxRendererGL.cpp
@@ -64,6 +64,18 @@
#endif
+#ifdef TARGET_DARWIN
+#if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_4
+ #include <CoreVideo/CoreVideo.h>
+ #include <OpenGL/CGLIOSurface.h>
+#else
+ enum CVPixelBufferLockFlags {
+ kCVPixelBufferLock_ReadOnly = 0x00000001,
+ };
+ #include <CoreVideo/CVPixelBuffer.h>
+#endif
+#endif
+
#ifdef HAS_GLX
#include <GL/glx.h>
#endif
@@ -136,7 +148,12 @@ CLinuxRendererGL::CLinuxRendererGL()
{
m_textureTarget = GL_TEXTURE_2D;
for (int i = 0; i < NUM_BUFFERS; i++)
+ {
m_eventTexturesDone[i] = new CEvent(false,true);
+#ifdef TARGET_DARWIN
+ m_buffers[i].cvBufferRef = NULL;
+#endif
+ }
m_renderMethod = RENDER_GLSL;
m_renderQuality = RQ_SINGLEPASS;
@@ -765,6 +782,9 @@ unsigned int CLinuxRendererGL::PreInit()
m_formats.push_back(RENDER_FMT_NV12);
m_formats.push_back(RENDER_FMT_YUYV422);
m_formats.push_back(RENDER_FMT_UYVY422);
+#ifdef TARGET_DARWIN
+ m_formats.push_back(RENDER_FMT_CVBREF);
+#endif
// setup the background colour
m_clearColour = (float)(g_advancedSettings.m_videoBlackBarColour & 0xff) / 0xff;
@@ -925,6 +945,11 @@ void CLinuxRendererGL::LoadShaders(int field)
CLog::Log(LOGNOTICE, "GL: Using VAAPI render method");
m_renderMethod = RENDER_VAAPI;
}
+ else if (m_format == RENDER_FMT_CVBREF)
+ {
+ CLog::Log(LOGNOTICE, "GL: Using CoreVideoRef render method");
+ m_renderMethod = RENDER_CVREF;
+ }
else
{
int requestedMethod = g_guiSettings.GetInt("videoplayer.rendermethod");
@@ -1025,7 +1050,9 @@ void CLinuxRendererGL::LoadShaders(int field)
CLog::Log(LOGNOTICE, "GL: NPOT texture support detected");
- if (m_pboSupported && !(m_renderMethod & RENDER_SW))
+ if (m_pboSupported &&
+ !(m_renderMethod & RENDER_SW) &&
+ !(m_renderMethod & RENDER_CVREF))
{
CLog::Log(LOGNOTICE, "GL: Using GL_ARB_pixel_buffer_object");
m_pboUsed = true;
@@ -1059,6 +1086,12 @@ void CLinuxRendererGL::LoadShaders(int field)
m_textureCreate = &CLinuxRendererGL::CreateVAAPITexture;
m_textureDelete = &CLinuxRendererGL::DeleteVAAPITexture;
}
+ else if (m_format == RENDER_FMT_CVBREF)
+ {
+ m_textureUpload = &CLinuxRendererGL::UploadCVRefTexture;
+ m_textureCreate = &CLinuxRendererGL::CreateCVRefTexture;
+ m_textureDelete = &CLinuxRendererGL::DeleteCVRefTexture;
+ }
else
{
// setup default YV12 texture handlers
@@ -1159,6 +1192,12 @@ void CLinuxRendererGL::Render(DWORD flags, int renderBuffer)
RenderVAAPI(renderBuffer, m_currentField);
}
#endif
+#ifdef TARGET_DARWIN
+ else if (m_renderMethod & RENDER_CVREF)
+ {
+ RenderCoreVideoRef(renderBuffer, m_currentField);
+ }
+#endif
else
{
RenderSoftware(renderBuffer, m_currentField);
@@ -1625,6 +1664,38 @@ void CLinuxRendererGL::RenderVAAPI(int index, int field)
#endif
}
+void CLinuxRendererGL::RenderCoreVideoRef(int index, int field)
+{
+#ifdef TARGET_DARWIN
+ YUVPLANE &plane = m_buffers[index].fields[field][0];
+
+ glDisable(GL_DEPTH_TEST);
+
+ // Y
@bobo1on1
bobo1on1 added a note

That c/p'd comment is not relevant here ;)

@davilla Owner
davilla added a note

noted

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glActiveTextureARB(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, plane.id);
+ glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
@bobo1on1
bobo1on1 added a note

We use GL_MODULATE instead of GL_REPLACE for blending to work correctly, are you sure this is ok?

@davilla Owner
davilla added a note

changed to GL_MODULATE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
+
+ glBegin(GL_QUADS);
+ glTexCoord2f(plane.rect.x1, plane.rect.y1);
+ glVertex4f(m_destRect.x1, m_destRect.y1, 0, 1.0f );
+
+ glTexCoord2f(plane.rect.x2, plane.rect.y1);
+ glVertex4f(m_destRect.x2, m_destRect.y1, 0, 1.0f);
+
+ glTexCoord2f(plane.rect.x2, plane.rect.y2);
+ glVertex4f(m_destRect.x2, m_destRect.y2, 0, 1.0f);
+
+ glTexCoord2f(plane.rect.x1, plane.rect.y2);
+ glVertex4f(m_destRect.x1, m_destRect.y2, 0, 1.0f);
+
+ glEnd();
+
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+#endif
+}
+
void CLinuxRendererGL::RenderSoftware(int index, int field)
{
YUVPLANES &planes = m_buffers[index].fields[field];
@@ -2400,6 +2471,132 @@ void CLinuxRendererGL::UploadVAAPITexture(int index)
#endif
}
+//********************************************************************************************************
+// CoreVideoRef Texture creation, deletion, copying + clearing
+//********************************************************************************************************
+void CLinuxRendererGL::UploadCVRefTexture(int index)
+{
+#ifdef TARGET_DARWIN
+ CVBufferRef cvBufferRef = m_buffers[index].cvBufferRef;
+
+ if (cvBufferRef)
+ {
+ YUVFIELDS &fields = m_buffers[index].fields;
+ YUVPLANE &plane = fields[0][0];
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+ CVPixelBufferLockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
+ int bufferWidth = CVPixelBufferGetWidth(cvBufferRef);
+ int bufferHeight = CVPixelBufferGetHeight(cvBufferRef);
+ unsigned char *bufferBase = (unsigned char *)CVPixelBufferGetBaseAddress(cvBufferRef);
+
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, plane.id);
+ // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
+ // Using GL_YCBCR_422_APPLE extension to pull in video frame data directly
+ glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, bufferWidth, bufferHeight, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, bufferBase);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+ CVPixelBufferUnlockBaseAddress(cvBufferRef, kCVPixelBufferLock_ReadOnly);
+#else
+ // CGLTexImageIOSurface2D only exits in 10.5sdk and above.
+ // It is the fastest way to render a CVPixelBuffer backed
+ // with an IOSurface as there is no CPU -> GPU upload.
+ CGLContextObj cgl_ctx = (CGLContextObj)g_Windowing.GetCGLContextObj();
+ IOSurfaceRef surface = CVPixelBufferGetIOSurface(cvBufferRef);
+ GLsizei texWidth = IOSurfaceGetWidth(surface);
+ GLsizei texHeight= IOSurfaceGetHeight(surface);
+ OSType format_type = CVPixelBufferGetPixelFormatType(cvBufferRef);
+
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, plane.id);
+ if (format_type == kCVPixelFormatType_422YpCbCr8)
+ CGLTexImageIOSurface2D(cgl_ctx, GL_TEXTURE_RECTANGLE_ARB, GL_RGB8,
+ texWidth, texHeight, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, surface, 0);
+ else if (format_type == kCVPixelFormatType_32BGRA)
+ CGLTexImageIOSurface2D(cgl_ctx, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA8,
+ texWidth, texHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, surface, 0);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+#endif
+
+ CVBufferRelease(cvBufferRef);
+ m_buffers[index].cvBufferRef = NULL;
+
+ // Calculate Texture Source Rects
+ plane.rect = m_sourceRect;
+ plane.width = m_buffers[index].image.width;
+ plane.height = m_buffers[index].image.height;
+ plane.flipindex = m_buffers[index].flipindex;
+ }
+
+ m_eventTexturesDone[index]->Set();
+#endif
+}
+
+void CLinuxRendererGL::DeleteCVRefTexture(int index)
+{
+#ifdef TARGET_DARWIN
+ YUVPLANE &plane = m_buffers[index].fields[0][0];
+
+ if (m_buffers[index].cvBufferRef)
+ CVBufferRelease(m_buffers[index].cvBufferRef);
+ m_buffers[index].cvBufferRef = NULL;
+
+ if (plane.id && glIsTexture(plane.id))
+ glDeleteTextures(1, &plane.id), plane.id = 0;
+#endif
+}
+
+bool CLinuxRendererGL::CreateCVRefTexture(int index)
+{
+#ifdef TARGET_DARWIN
+ YV12Image &im = m_buffers[index].image;
+ YUVFIELDS &fields = m_buffers[index].fields;
+ YUVPLANE &plane = fields[0][0];
+
+ DeleteCVRefTexture(index);
+
+ memset(&im , 0, sizeof(im));
+ memset(&fields, 0, sizeof(fields));
+
+ im.height = m_sourceHeight;
+ im.width = m_sourceWidth;
+
+ plane.texwidth = im.width;
+ plane.texheight = im.height;
+ plane.pixpertex_x = 1;
+ plane.pixpertex_y = 1;
+
+ if(m_renderMethod & RENDER_POT)
+ {
+ plane.texwidth = NP2(plane.texwidth);
+ plane.texheight = NP2(plane.texheight);
+ }
+ glEnable(GL_TEXTURE_RECTANGLE_ARB);
+ glGenTextures(1, &plane.id);
+
+#if MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_5
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, plane.id);
+ // Set storage hint. Can also use GL_STORAGE_SHARED_APPLE see docs.
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_STORAGE_HINT_APPLE , GL_STORAGE_CACHED_APPLE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ // This is necessary for non-power-of-two textures
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, GL_RGBA, plane.texwidth, plane.texheight, 0, GL_YCBCR_422_APPLE, GL_UNSIGNED_SHORT_8_8_APPLE, NULL);
+ glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+#endif
+ glDisable(GL_TEXTURE_RECTANGLE_ARB);
+
+ m_eventTexturesDone[index]->Set();
+#endif
+ return true;
+}
+
void CLinuxRendererGL::UploadYUV422PackedTexture(int source)
{
YUVBUFFER& buf = m_buffers[source];
@@ -3201,4 +3398,16 @@ void CLinuxRendererGL::AddProcessor(VAAPI::CHolder& holder)
}
#endif
+#ifdef TARGET_DARWIN
+void CLinuxRendererGL::AddProcessor(struct __CVBuffer *cvBufferRef)
+{
+ YUVBUFFER &buf = m_buffers[NextYV12Texture()];
+ if (buf.cvBufferRef)
+ CVBufferRelease(buf.cvBufferRef);
+ buf.cvBufferRef = cvBufferRef;
+ // retain another reference, this way dvdplayer and renderer can issue releases.
+ CVBufferRetain(buf.cvBufferRef);
+}
+#endif
+
#endif
View
12 xbmc/cores/VideoRenderers/LinuxRendererGL.h
@@ -91,6 +91,7 @@ enum RenderMethod
RENDER_VDPAU=0x08,
RENDER_POT=0x10,
RENDER_VAAPI=0x20,
+ RENDER_CVREF = 0x40,
};
enum RenderQuality
@@ -145,6 +146,9 @@ class CLinuxRendererGL : public CBaseRenderer
#ifdef HAVE_LIBVA
virtual void AddProcessor(VAAPI::CHolder& holder);
#endif
+#ifdef TARGET_DARWIN
+ virtual void AddProcessor(struct __CVBuffer *cvBufferRef);
+#endif
virtual void RenderUpdate(bool clear, DWORD flags = 0, DWORD alpha = 255);
@@ -193,6 +197,10 @@ class CLinuxRendererGL : public CBaseRenderer
void DeleteVAAPITexture(int index);
bool CreateVAAPITexture(int index);
+ void UploadCVRefTexture(int index);
+ void DeleteCVRefTexture(int index);
+ bool CreateCVRefTexture(int index);
+
void UploadYUV422PackedTexture(int index);
void DeleteYUV422PackedTexture(int index);
bool CreateYUV422PackedTexture(int index);
@@ -210,6 +218,7 @@ class CLinuxRendererGL : public CBaseRenderer
void RenderSoftware(int renderBuffer, int field); // single pass s/w yuv2rgb renderer
void RenderVDPAU(int renderBuffer, int field); // render using vdpau hardware
void RenderVAAPI(int renderBuffer, int field); // render using vdpau hardware
+ void RenderCoreVideoRef(int renderBuffer, int field);// CoreVideo reference
CFrameBufferObject m_fbo;
@@ -271,6 +280,9 @@ class CLinuxRendererGL : public CBaseRenderer
#ifdef HAVE_LIBVA
VAAPI::CHolder& vaapi;
#endif
+#ifdef TARGET_DARWIN_OSX
+ struct __CVBuffer *cvBufferRef;
+#endif
};
typedef YUVBUFFER YUVBUFFERS[NUM_BUFFERS];
View
2  xbmc/cores/VideoRenderers/RenderManager.cpp
@@ -840,7 +840,7 @@ int CXBMCRenderManager::AddVideoPicture(DVDVideoPicture& pic)
else if(pic.format == RENDER_FMT_OMXEGL)
m_pRenderer->AddProcessor(pic.openMax, &pic);
#endif
-#ifdef HAVE_VIDEOTOOLBOXDECODER
+#ifdef TARGET_DARWIN
else if(pic.format == RENDER_FMT_CVBREF)
m_pRenderer->AddProcessor(pic.cvBufferRef);
#endif
View
200 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.cpp
@@ -87,6 +87,7 @@ enum {
kCVPixelFormatType_422YpCbCr8 = FourCharCode('2vuy'),
kCVPixelFormatType_32BGRA = FourCharCode('BGRA')
};
+const CFStringRef kCVPixelBufferIOSurfacePropertiesKey = CFSTR("IOSurfaceProperties");
#endif
////////////////////////////////////////////////////////////////////////////////////////////
@@ -640,8 +641,6 @@ CDVDVideoCodecVDA::CDVDVideoCodecVDA() : CDVDVideoCodec()
m_convert_3byteTo4byteNALSize = false;
m_dllAvUtil = NULL;
m_dllAvFormat = NULL;
- m_dllSwScale = NULL;
- memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
}
CDVDVideoCodecVDA::~CDVDVideoCodecVDA()
@@ -803,14 +802,6 @@ bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
return false;
}
- // input stream is qualified, now we can load dlls.
- m_dllSwScale = new DllSwScale;
- if (!m_dllSwScale->Load())
- {
- CFRelease(avcCData);
- return false;
- }
-
// setup the decoder configuration dict
CFMutableDictionaryRef decoderConfiguration = CFDictionaryCreateMutable(
kCFAllocatorDefault, 4, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
@@ -832,20 +823,28 @@ bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
// setup the destination image buffer dict, vda will output this pict format
CFMutableDictionaryRef destinationImageBufferAttributes = CFDictionaryCreateMutable(
- kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
-
+ kCFAllocatorDefault, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
OSType cvPixelFormatType = kCVPixelFormatType_422YpCbCr8;
CFNumberRef pixelFormat = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &cvPixelFormatType);
- CFDictionarySetValue(destinationImageBufferAttributes, kCVPixelBufferPixelFormatTypeKey, pixelFormat);
- // release the retained object refs, destinationImageBufferAttributes owns it now
+
+ // an IOSurface properties dictionary
+ CFDictionaryRef iosurfaceDictionary = CFDictionaryCreate(kCFAllocatorDefault,
+ NULL, NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
+
+ CFDictionarySetValue(destinationImageBufferAttributes,
+ kCVPixelBufferPixelFormatTypeKey, pixelFormat);
+ CFDictionarySetValue(destinationImageBufferAttributes,
+ kCVPixelBufferIOSurfacePropertiesKey, iosurfaceDictionary);
+ // release the retained object refs, destinationImageBufferAttributes owns them now
CFRelease(pixelFormat);
+ CFRelease(iosurfaceDictionary);
// create the VDADecoder object
OSStatus status;
try
{
status = m_dll->VDADecoderCreate(decoderConfiguration, destinationImageBufferAttributes,
- (VDADecoderOutputCallback *)VDADecoderCallback, this, (VDADecoder*)&m_vda_decoder);
+ (VDADecoderOutputCallback*)VDADecoderCallback, this, (VDADecoder*)&m_vda_decoder);
}
catch (...)
{
@@ -856,46 +855,15 @@ bool CDVDVideoCodecVDA::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options)
CFRelease(destinationImageBufferAttributes);
if (status != kVDADecoderNoErr)
{
- if (status == kVDADecoderDecoderFailedErr)
- CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, currently in use by another process",
- __FUNCTION__);
- else
- CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, status(%d), profile(%d), level(%d)",
- __FUNCTION__, (int)status, profile, level);
+ if (status == kVDADecoderDecoderFailedErr)
+ CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, currently in use by another process",
+ __FUNCTION__);
+ else
+ CLog::Log(LOGNOTICE, "%s - VDADecoder Codec failed to open, status(%d), profile(%d), level(%d)",
+ __FUNCTION__, (int)status, profile, level);
return false;
}
- // allocate a YV12 DVDVideoPicture buffer.
- // first make sure all properties are reset.
- memset(&m_videobuffer, 0, sizeof(DVDVideoPicture));
- unsigned int iPixels = width * height;
- unsigned int iChromaPixels = iPixels/4;
-
- m_videobuffer.pts = DVD_NOPTS_VALUE;
- m_videobuffer.iFlags = DVP_FLAG_ALLOCATED;
- m_videobuffer.format = RENDER_FMT_YUV420P;
- m_videobuffer.color_range = 0;
- m_videobuffer.color_matrix = 4;
- m_videobuffer.iWidth = width;
- m_videobuffer.iHeight = height;
- m_videobuffer.iDisplayWidth = width;
- m_videobuffer.iDisplayHeight = height;
-
- m_videobuffer.iLineSize[0] = width; //Y
- m_videobuffer.iLineSize[1] = width/2; //U
- m_videobuffer.iLineSize[2] = width/2; //V
- m_videobuffer.iLineSize[3] = 0;
-
- m_videobuffer.data[0] = (BYTE*)malloc(iPixels); //Y
- m_videobuffer.data[1] = (BYTE*)malloc(iChromaPixels); //U
- m_videobuffer.data[2] = (BYTE*)malloc(iChromaPixels); //V
- m_videobuffer.data[3] = NULL;
-
- // set all data to 0 for less artifacts.. hmm.. what is black in YUV??
- memset(m_videobuffer.data[0], 0, iPixels);
- memset(m_videobuffer.data[1], 0, iChromaPixels);
- memset(m_videobuffer.data[2], 0, iChromaPixels);
-
m_DropPictures = false;
m_max_ref_frames = std::min(m_max_ref_frames, 5);
m_sort_time_offset = (CurrentHostCounter() * 1000.0) / CurrentHostFrequency();
@@ -910,32 +878,13 @@ void CDVDVideoCodecVDA::Dispose()
{
CCocoaAutoPool pool;
if (m_vda_decoder)
- {
- m_dll->VDADecoderDestroy((VDADecoder)m_vda_decoder);
- m_vda_decoder = NULL;
- }
- if (m_videobuffer.iFlags & DVP_FLAG_ALLOCATED)
- {
- free(m_videobuffer.data[0]);
- free(m_videobuffer.data[1]);
- free(m_videobuffer.data[2]);
- m_videobuffer.iFlags = 0;
- }
+ m_dll->VDADecoderDestroy((VDADecoder)m_vda_decoder), m_vda_decoder = NULL;
+
if (m_dllAvUtil)
- {
- delete m_dllAvUtil;
- m_dllAvUtil = NULL;
- }
+ delete m_dllAvUtil, m_dllAvUtil = NULL;
+
if (m_dllAvFormat)
- {
- delete m_dllAvFormat;
- m_dllAvFormat = NULL;
- }
- if (m_dllSwScale)
- {
- delete m_dllSwScale;
- m_dllSwScale = NULL;
- }
+ delete m_dllAvFormat, m_dllAvFormat = NULL;
}
void CDVDVideoCodecVDA::SetDropState(bool bDrop)
@@ -1016,9 +965,7 @@ int CDVDVideoCodecVDA::Decode(BYTE* pData, int iSize, double dts, double pts)
}
if (m_queue_depth < m_max_ref_frames)
- {
return VC_BUFFER;
- }
return VC_PICTURE | VC_BUFFER;
}
@@ -1036,86 +983,42 @@ void CDVDVideoCodecVDA::Reset(void)
bool CDVDVideoCodecVDA::GetPicture(DVDVideoPicture* pDvdVideoPicture)
{
- CCocoaAutoPool pool;
- FourCharCode pixel_buffer_format;
- CVPixelBufferRef picture_buffer_ref;
-
- // clone the video picture buffer settings.
- *pDvdVideoPicture = m_videobuffer;
-
// get the top yuv frame, we risk getting the wrong frame if the frame queue
// depth is less than the number of encoded reference frames. If queue depth
// is greater than the number of encoded reference frames, then the top frame
- // will never change and we can just grab a ref to the top frame. This way
- // we don't lockout the vdadecoder while doing color format convert.
+ // will never change and we can just grab a ref to the top frame.
pthread_mutex_lock(&m_queue_mutex);
- picture_buffer_ref = m_display_queue->pixel_buffer_ref;
- pixel_buffer_format = m_display_queue->pixel_buffer_format;
- pDvdVideoPicture->dts = m_display_queue->dts;
- pDvdVideoPicture->pts = m_display_queue->pts;
+ pDvdVideoPicture->dts = m_display_queue->dts;
+ pDvdVideoPicture->pts = m_display_queue->pts;
+ pDvdVideoPicture->cvBufferRef = m_display_queue->pixel_buffer_ref;
+ m_display_queue->pixel_buffer_ref = NULL;
pthread_mutex_unlock(&m_queue_mutex);
- // lock the CVPixelBuffer down
- CVPixelBufferLockBaseAddress(picture_buffer_ref, 0);
- int row_stride = CVPixelBufferGetBytesPerRowOfPlane(picture_buffer_ref, 0);
- uint8_t *base_ptr = (uint8_t*)CVPixelBufferGetBaseAddressOfPlane(picture_buffer_ref, 0);
- if (base_ptr)
- {
- if (pixel_buffer_format == kCVPixelFormatType_422YpCbCr8)
- UYVY422_to_YUV420P(base_ptr, row_stride, pDvdVideoPicture);
- else if (pixel_buffer_format == kCVPixelFormatType_32BGRA)
- BGRA_to_YUV420P(base_ptr, row_stride, pDvdVideoPicture);
- }
- // unlock the CVPixelBuffer
- CVPixelBufferUnlockBaseAddress(picture_buffer_ref, 0);
+ pDvdVideoPicture->format = RENDER_FMT_CVBREF;
+ pDvdVideoPicture->iFlags = DVP_FLAG_ALLOCATED;
+ pDvdVideoPicture->color_range = 0;
+ pDvdVideoPicture->color_matrix = 4;
+ pDvdVideoPicture->iWidth = CVPixelBufferGetWidth(pDvdVideoPicture->cvBufferRef);
+ pDvdVideoPicture->iHeight = CVPixelBufferGetHeight(pDvdVideoPicture->cvBufferRef);
+ pDvdVideoPicture->iDisplayWidth = pDvdVideoPicture->iWidth;
+ pDvdVideoPicture->iDisplayHeight = pDvdVideoPicture->iHeight;
// now we can pop the top frame.
DisplayQueuePop();
-
//CLog::Log(LOGNOTICE, "%s - VDADecoderDecode dts(%f), pts(%f)", __FUNCTION__,
// pDvdVideoPicture->dts, pDvdVideoPicture->pts);
return VC_PICTURE | VC_BUFFER;
}
-void CDVDVideoCodecVDA::UYVY422_to_YUV420P(uint8_t *yuv422_ptr, int yuv422_stride, DVDVideoPicture *picture)
+bool CDVDVideoCodecVDA::ClearPicture(DVDVideoPicture* pDvdVideoPicture)
{
- // convert PIX_FMT_UYVY422 to PIX_FMT_YUV420P.
- struct SwsContext *swcontext = m_dllSwScale->sws_getContext(
- m_videobuffer.iWidth, m_videobuffer.iHeight, PIX_FMT_UYVY422,
- m_videobuffer.iWidth, m_videobuffer.iHeight, PIX_FMT_YUV420P,
- SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);
- if (swcontext)
- {
- uint8_t *src[] = { yuv422_ptr, 0, 0, 0 };
- int srcStride[] = { yuv422_stride, 0, 0, 0 };
+ // release any previous retained image buffer ref that
+ // has not been passed up to renderer (ie. dropped frames, etc).
+ if (pDvdVideoPicture->cvBufferRef)
+ CVBufferRelease(pDvdVideoPicture->cvBufferRef);
- uint8_t *dst[] = { picture->data[0], picture->data[1], picture->data[2], 0 };
- int dstStride[] = { picture->iLineSize[0], picture->iLineSize[1], picture->iLineSize[2], 0 };
-
- m_dllSwScale->sws_scale(swcontext, src, srcStride, 0, picture->iHeight, dst, dstStride);
- m_dllSwScale->sws_freeContext(swcontext);
- }
-}
-
-void CDVDVideoCodecVDA::BGRA_to_YUV420P(uint8_t *bgra_ptr, int bgra_stride, DVDVideoPicture *picture)
-{
- // convert PIX_FMT_BGRA to PIX_FMT_YUV420P.
- struct SwsContext *swcontext = m_dllSwScale->sws_getContext(
- m_videobuffer.iWidth, m_videobuffer.iHeight, PIX_FMT_BGRA,
- m_videobuffer.iWidth, m_videobuffer.iHeight, PIX_FMT_YUV420P,
- SWS_FAST_BILINEAR | SwScaleCPUFlags(), NULL, NULL, NULL);
- if (swcontext)
- {
- uint8_t *src[] = { bgra_ptr, 0, 0, 0 };
- int srcStride[] = { bgra_stride, 0, 0, 0 };
-
- uint8_t *dst[] = { picture->data[0], picture->data[1], picture->data[2], 0 };
- int dstStride[] = { picture->iLineSize[0], picture->iLineSize[1], picture->iLineSize[2], 0 };
-
- m_dllSwScale->sws_scale(swcontext, src, srcStride, 0, picture->iHeight, dst, dstStride);
- m_dllSwScale->sws_freeContext(swcontext);
- }
+ return CDVDVideoCodec::ClearPicture(pDvdVideoPicture);
}
void CDVDVideoCodecVDA::DisplayQueuePop(void)
@@ -1132,16 +1035,17 @@ void CDVDVideoCodecVDA::DisplayQueuePop(void)
pthread_mutex_unlock(&m_queue_mutex);
// and release it
- CVPixelBufferRelease(top_frame->pixel_buffer_ref);
+ if (top_frame->pixel_buffer_ref)
+ CVBufferRelease(top_frame->pixel_buffer_ref);
free(top_frame);
}
void CDVDVideoCodecVDA::VDADecoderCallback(
- void *decompressionOutputRefCon,
- CFDictionaryRef frameInfo,
- OSStatus status,
- uint32_t infoFlags,
- CVImageBufferRef imageBuffer)
+ void *decompressionOutputRefCon,
+ CFDictionaryRef frameInfo,
+ OSStatus status,
+ uint32_t infoFlags,
+ CVImageBufferRef imageBuffer)
{
CCocoaAutoPool pool;
// Warning, this is an async callback. There can be multiple frames in flight.
@@ -1172,7 +1076,7 @@ void CDVDVideoCodecVDA::VDADecoderCallback(
frame_queue *newFrame = (frame_queue*)calloc(sizeof(frame_queue), 1);
newFrame->nextframe = NULL;
newFrame->pixel_buffer_format = format_type;
- newFrame->pixel_buffer_ref = CVPixelBufferRetain(imageBuffer);
+ newFrame->pixel_buffer_ref = CVBufferRetain(imageBuffer);
GetFrameDisplayTimeFromDictionary(frameInfo, newFrame);
// if both dts or pts are good we use those, else use decoder insert time for frame sort
View
8 xbmc/cores/dvdplayer/DVDCodecs/Video/DVDVideoCodecVDA.h
@@ -31,7 +31,7 @@ typedef struct frame_queue {
double pts;
double sort_time;
FourCharCode pixel_buffer_format;
- CVPixelBufferRef pixel_buffer_ref;
+ CVBufferRef pixel_buffer_ref;
struct frame_queue *nextframe;
} frame_queue;
@@ -51,13 +51,12 @@ class CDVDVideoCodecVDA : public CDVDVideoCodec
virtual int Decode(BYTE *pData, int iSize, double dts, double pts);
virtual void Reset(void);
virtual bool GetPicture(DVDVideoPicture *pDvdVideoPicture);
+ virtual bool ClearPicture(DVDVideoPicture* pDvdVideoPicture);
virtual void SetDropState(bool bDrop);
virtual const char* GetName(void) { return (const char*)m_pFormatName; }
protected:
void DisplayQueuePop(void);
- void UYVY422_to_YUV420P(uint8_t *yuv422_ptr, int yuv422_stride, DVDVideoPicture *picture);
- void BGRA_to_YUV420P(uint8_t *bgra_ptr, int bgra_stride, DVDVideoPicture *picture);
static void VDADecoderCallback(
void *decompressionOutputRefCon, CFDictionaryRef frameInfo,
@@ -79,9 +78,6 @@ class CDVDVideoCodecVDA : public CDVDVideoCodec
bool m_convert_3byteTo4byteNALSize;
DllAvUtil *m_dllAvUtil;
DllAvFormat *m_dllAvFormat;
-
- DllSwScale *m_dllSwScale;
- DVDVideoPicture m_videobuffer;
};
#endif
View
3  xbmc/windowing/osx/WinSystemOSX.h
@@ -63,6 +63,9 @@ class CWinSystemOSX : public CWinSystemBase
virtual int GetNumScreens();
void CheckDisplayChanging(u_int32_t flags);
+
+ void* GetCGLContextObj();
+
protected:
void* CreateWindowedContext(void* shareCtx);
void* CreateFullScreenContext(int screen_index, void* shareCtx);
View
5 xbmc/windowing/osx/WinSystemOSX.mm
@@ -1398,4 +1398,9 @@ static void DisplayReconfigured(CGDirectDisplayID display,
}
}
+void* CWinSystemOSX::GetCGLContextObj()
+{
+ return [(NSOpenGLContext*)m_glContext CGLContextObj];
+}
+
#endif
@bobo1on1

That c/p'd comment is not relevant here ;)

@bobo1on1

We use GL_MODULATE instead of GL_REPLACE for blending to work correctly, are you sure this is ok?

@davilla

changed to GL_MODULATE

Please sign in to comment.
Something went wrong with that request. Please try again.