mirror of https://github.com/odrling/Aegisub
Made YV12->RGB32 conversion happen before subtitling, so asa works without glitching.
Originally committed to SVN as r982.
This commit is contained in:
parent
4e2af4cd57
commit
246be56350
|
@ -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;
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
Loading…
Reference in New Issue