Made YV12->RGB32 conversion happen before subtitling, so asa works without glitching.

Originally committed to SVN as r982.
This commit is contained in:
Rodrigo Braz Monteiro 2007-04-03 02:55:43 +00:00
parent 4e2af4cd57
commit 246be56350
2 changed files with 57 additions and 51 deletions

View File

@ -265,10 +265,11 @@ void OpenGLWrapper::SetModeFill() {
////////////////////////// //////////////////////////
// Are shaders available? // Are shaders available?
bool OpenGLWrapper::ShadersAvailable() { bool OpenGLWrapper::ShadersAvailable() {
bool available = IsExtensionSupported("GL_ARB_vertex_shader") && IsExtensionSupported("GL_ARB_fragment_shader");
static bool first = true; static bool first = true;
static bool available = false;
if (first) { if (first) {
first = false; first = false;
available = IsExtensionSupported("GL_ARB_vertex_shader") && IsExtensionSupported("GL_ARB_fragment_shader");
if (!available) wxMessageBox(_T("Warning, OpenGL shaders are not available on this machine. YV12 video will be on greyscale."),_T("GL Shaders Error")); if (!available) wxMessageBox(_T("Warning, OpenGL shaders are not available on this machine. YV12 video will be on greyscale."),_T("GL Shaders Error"));
} }
return available; return available;

View File

@ -400,29 +400,19 @@ wxGLContext *VideoContext::GetGLContext(wxGLCanvas *canvas) {
} }
/////////////////////////// ////////////////////////
// Get GL Texture of frame // Requests a new frame
GLuint VideoContext::GetFrameAsTexture(int n) { AegiVideoFrame VideoContext::GetFrame(int n) {
// Already uploaded // Current frame if -1
if (n == lastFrame || n == -1) return lastTex; if (n == -1) n = frame_n;
// Get frame // Get frame
AegiVideoFrame frame = GetFrame(n); AegiVideoFrame frame = provider->GetFrame(n);
AegiVideoFrame *srcFrame = &frame; AegiVideoFrame *srcFrame = &frame;
// Set frame // Convert to YV12 if it can't be handled
lastFrame = n;
// Set context
GetGLContext(displayList.front())->SetCurrent(*displayList.front());
glEnable(GL_TEXTURE_2D);
if (glGetError() != 0) throw _T("Error enabling texture.");
// Deal with YV12
bool doMakeShader = false;
if (frame.format == FORMAT_YV12 && yv12shader == 0) { if (frame.format == FORMAT_YV12 && yv12shader == 0) {
doMakeShader = OpenGLWrapper::UseShaders(); if (!OpenGLWrapper::UseShaders()) {
if (!doMakeShader) {
tempRGBFrame.w = frame.w; tempRGBFrame.w = frame.w;
tempRGBFrame.h = frame.h; tempRGBFrame.h = frame.h;
tempRGBFrame.pitch[0] = frame.w * 4; tempRGBFrame.pitch[0] = frame.w * 4;
@ -432,20 +422,49 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
} }
} }
// Raster subtitles if available/necessary
if (subsProvider && subsProvider->CanRaster()) {
tempFrame.CopyFrom(*srcFrame);
subsProvider->DrawSubtitles(tempFrame,VFR_Input.GetTimeAtFrame(n,true,true)/1000.0);
return tempFrame;
}
// Return pure frame
else return *srcFrame;
}
///////////////////////////
// Get GL Texture of frame
GLuint VideoContext::GetFrameAsTexture(int n) {
// Already uploaded
if (n == lastFrame || n == -1) return lastTex;
// Get frame
AegiVideoFrame frame = GetFrame(n);
// Set frame
lastFrame = n;
// Set context
GetGLContext(displayList.front())->SetCurrent(*displayList.front());
glEnable(GL_TEXTURE_2D);
if (glGetError() != 0) throw _T("Error enabling texture.");
// Image type // Image type
GLenum format = GL_LUMINANCE; GLenum format = GL_LUMINANCE;
if (srcFrame->format == FORMAT_RGB32) { if (frame.format == FORMAT_RGB32) {
if (srcFrame->invertChannels) format = GL_BGRA_EXT; if (frame.invertChannels) format = GL_BGRA_EXT;
else format = GL_RGBA; else format = GL_RGBA;
} }
else if (srcFrame->format == FORMAT_RGB24) { else if (frame.format == FORMAT_RGB24) {
if (srcFrame->invertChannels) format = GL_BGR_EXT; if (frame.invertChannels) format = GL_BGR_EXT;
else format = GL_RGB; else format = GL_RGB;
} }
else if (srcFrame->format == FORMAT_YV12) { else if (frame.format == FORMAT_YV12) {
format = GL_LUMINANCE; format = GL_LUMINANCE;
} }
isInverted = srcFrame->flipped; isInverted = frame.flipped;
if (lastTex == 0) { if (lastTex == 0) {
// Enable // Enable
@ -469,9 +488,9 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
if (glGetError() != 0) throw _T("Error setting wrap_t texture parameter."); if (glGetError() != 0) throw _T("Error setting wrap_t texture parameter.");
// Load image data into texture // Load image data into texture
int height = srcFrame->h; int height = frame.h;
if (srcFrame->format == FORMAT_YV12) height = height * 3 / 2; if (frame.format == FORMAT_YV12) height = height * 3 / 2;
int tw = SmallestPowerOf2(MAX(srcFrame->pitch[0]/srcFrame->GetBpp(0),srcFrame->pitch[1]+srcFrame->pitch[2])); int tw = SmallestPowerOf2(MAX(frame.pitch[0]/frame.GetBpp(0),frame.pitch[1]+frame.pitch[2]));
int th = SmallestPowerOf2(height); int th = SmallestPowerOf2(height);
glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,tw,th,0,format,GL_UNSIGNED_BYTE,NULL); glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA8,tw,th,0,format,GL_UNSIGNED_BYTE,NULL);
if (glGetError() != 0) { if (glGetError() != 0) {
@ -483,16 +502,16 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
if (glGetError() != 0) throw _T("Error allocating texture."); if (glGetError() != 0) throw _T("Error allocating texture.");
} }
} }
texW = float(srcFrame->w)/float(tw); texW = float(frame.w)/float(tw);
texH = float(srcFrame->h)/float(th); texH = float(frame.h)/float(th);
// Set texture // Set texture
//glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST); //glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
//if (glGetError() != 0) throw _T("Error setting hinting."); //if (glGetError() != 0) throw _T("Error setting hinting.");
// Create shader // Create shader
if (doMakeShader) { if (frame.format == FORMAT_YV12 && yv12shader == 0 && OpenGLWrapper::UseShaders()) {
yv12shader = OpenGLWrapper::CreateYV12Shader(texW,texH,float(srcFrame->pitch[1])/float(tw)); yv12shader = OpenGLWrapper::CreateYV12Shader(texW,texH,float(frame.pitch[1])/float(tw));
} }
// Set priority // Set priority
@ -501,20 +520,20 @@ GLuint VideoContext::GetFrameAsTexture(int n) {
} }
// Load texture data // Load texture data
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,srcFrame->pitch[0]/srcFrame->GetBpp(0),srcFrame->h,format,GL_UNSIGNED_BYTE,srcFrame->data[0]); glTexSubImage2D(GL_TEXTURE_2D,0,0,0,frame.pitch[0]/frame.GetBpp(0),frame.h,format,GL_UNSIGNED_BYTE,frame.data[0]);
if (glGetError() != 0) throw _T("Error uploading primary plane"); if (glGetError() != 0) throw _T("Error uploading primary plane");
// UV planes for YV12 // UV planes for YV12
if (srcFrame->format == FORMAT_YV12) { if (frame.format == FORMAT_YV12) {
int u = 1; int u = 1;
int v = 2; int v = 2;
if (srcFrame->invertChannels) { if (frame.invertChannels) {
u = 2; u = 2;
v = 1; v = 1;
} }
glTexSubImage2D(GL_TEXTURE_2D,0,0,srcFrame->h,srcFrame->pitch[1],srcFrame->h/2,format,GL_UNSIGNED_BYTE,srcFrame->data[u]); glTexSubImage2D(GL_TEXTURE_2D,0,0,frame.h,frame.pitch[1],frame.h/2,format,GL_UNSIGNED_BYTE,frame.data[u]);
if (glGetError() != 0) throw _T("Error uploading U plane."); if (glGetError() != 0) throw _T("Error uploading U plane.");
glTexSubImage2D(GL_TEXTURE_2D,0,srcFrame->pitch[1],srcFrame->h,srcFrame->pitch[2],srcFrame->h/2,format,GL_UNSIGNED_BYTE,srcFrame->data[v]); glTexSubImage2D(GL_TEXTURE_2D,0,frame.pitch[1],frame.h,frame.pitch[2],frame.h/2,format,GL_UNSIGNED_BYTE,frame.data[v]);
if (glGetError() != 0) throw _T("Error uploadinv V plane."); if (glGetError() != 0) throw _T("Error uploadinv V plane.");
} }
@ -558,20 +577,6 @@ void VideoContext::SaveSnapshot() {
} }
////////////////////////
// Requests a new frame
AegiVideoFrame VideoContext::GetFrame(int n) {
if (n == -1) n = frame_n;
AegiVideoFrame frame = provider->GetFrame(n);
if (subsProvider && subsProvider->CanRaster()) {
tempFrame.CopyFrom(frame);
subsProvider->DrawSubtitles(tempFrame,VFR_Input.GetTimeAtFrame(n,true,true)/1000.0);
return tempFrame;
}
else return frame;
}
//////////////////////////// ////////////////////////////
// Get dimensions of script // Get dimensions of script
void VideoContext::GetScriptSize(int &sw,int &sh) { void VideoContext::GetScriptSize(int &sw,int &sh) {