diff options
author | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-12 01:22:08 +0000 |
---|---|---|
committer | hclam@chromium.org <hclam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-12 01:22:08 +0000 |
commit | 7b3cd164793d6dbf31dd340ad19f0bce61c8a2bc (patch) | |
tree | b9fdd2068d1e8260b18676a5fe3703db3c947ca3 /media | |
parent | 957aaba4166a51a2cf8125598f721a4685fef233 (diff) | |
download | chromium_src-7b3cd164793d6dbf31dd340ad19f0bce61c8a2bc.zip chromium_src-7b3cd164793d6dbf31dd340ad19f0bce61c8a2bc.tar.gz chromium_src-7b3cd164793d6dbf31dd340ad19f0bce61c8a2bc.tar.bz2 |
Implement GLES video renderer in player_x11
This patch does the following:
1. Split the implementation of X11 and GL into two separate files
2. Add implementation of GLES render
Review URL: http://codereview.chromium.org/596055
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38867 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/media.gyp | 40 | ||||
-rw-r--r-- | media/tools/player_x11/gl_video_renderer.cc | 313 | ||||
-rw-r--r-- | media/tools/player_x11/gl_video_renderer.h | 72 | ||||
-rw-r--r-- | media/tools/player_x11/gles_video_renderer.cc | 344 | ||||
-rw-r--r-- | media/tools/player_x11/gles_video_renderer.h | 75 | ||||
-rw-r--r-- | media/tools/player_x11/player_x11.cc | 18 | ||||
-rw-r--r-- | media/tools/player_x11/x11_video_renderer.cc | 348 | ||||
-rw-r--r-- | media/tools/player_x11/x11_video_renderer.h | 16 |
8 files changed, 910 insertions, 316 deletions
diff --git a/media/media.gyp b/media/media.gyp index 33481b5..c825fb3 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -5,6 +5,7 @@ { 'variables': { 'chromium_code': 1, + 'player_x11_renderer%': 'x11', }, 'target_defaults': { 'conditions': [ @@ -371,7 +372,6 @@ 'dependencies': [ 'media', '../base/base.gyp:base', - '../gpu/gpu.gyp:gl_libs', ], 'link_settings': { 'libraries': [ @@ -383,8 +383,42 @@ }, 'sources': [ 'tools/player_x11/player_x11.cc', - 'tools/player_x11/x11_video_renderer.cc', - 'tools/player_x11/x11_video_renderer.h', + ], + 'conditions' : [ + ['player_x11_renderer == "x11"', { + 'sources': [ + 'tools/player_x11/x11_video_renderer.cc', + 'tools/player_x11/x11_video_renderer.h', + ], + 'defines': [ + 'RENDERER_X11', + ], + }], + ['player_x11_renderer == "gles"', { + 'libraries': [ + '-lEGL', + '-lGLESv2', + ], + 'sources': [ + 'tools/player_x11/gles_video_renderer.cc', + 'tools/player_x11/gles_video_renderer.h', + ], + 'defines': [ + 'RENDERER_GLES', + ], + }], + ['player_x11_renderer == "gl"', { + 'dependencies': [ + '../gpu/gpu.gyp:gl_libs', + ], + 'sources': [ + 'tools/player_x11/gl_video_renderer.cc', + 'tools/player_x11/gl_video_renderer.h', + ], + 'defines': [ + 'RENDERER_GL', + ], + }], ], }, ], diff --git a/media/tools/player_x11/gl_video_renderer.cc b/media/tools/player_x11/gl_video_renderer.cc new file mode 100644 index 0000000..f2f623d --- /dev/null +++ b/media/tools/player_x11/gl_video_renderer.cc @@ -0,0 +1,313 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/tools/player_x11/gl_video_renderer.h" + +#include <dlfcn.h> +#include <X11/Xutil.h> +#include <X11/extensions/Xrender.h> +#include <X11/extensions/Xcomposite.h> + +#include "media/base/buffers.h" +#include "media/base/yuv_convert.h" + +GlVideoRenderer* GlVideoRenderer::instance_ = NULL; + +GlVideoRenderer::GlVideoRenderer(Display* display, Window window) + : display_(display), + window_(window), + new_frame_(false), + gl_context_(NULL) { +} + +GlVideoRenderer::~GlVideoRenderer() { +} + +// static +bool GlVideoRenderer::IsMediaFormatSupported( + const media::MediaFormat& media_format) { + int width = 0; + int height = 0; + return ParseMediaFormat(media_format, &width, &height); +} + +void GlVideoRenderer::OnStop() { + glXMakeCurrent(display_, 0, NULL); + glXDestroyContext(display_, gl_context_); +} + +static GLXContext InitGLContext(Display* display, Window window) { + // Some versions of NVIDIA's GL libGL.so include a broken version of + // dlopen/dlsym, and so linking it into chrome breaks it. So we dynamically + // load it, and use glew to dynamically resolve symbols. + // See http://code.google.com/p/chromium/issues/detail?id=16800 + void* handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL); + if (!handle) { + LOG(ERROR) << "Could not find libGL.so.1"; + return NULL; + } + if (glxewInit() != GLEW_OK) { + LOG(ERROR) << "GLXEW failed initialization"; + return NULL; + } + + XWindowAttributes attributes; + XGetWindowAttributes(display, window, &attributes); + XVisualInfo visual_info_template; + visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); + int visual_info_count = 0; + XVisualInfo* visual_info_list = XGetVisualInfo(display, VisualIDMask, + &visual_info_template, + &visual_info_count); + GLXContext context = NULL; + for (int i = 0; i < visual_info_count && !context; ++i) { + context = glXCreateContext(display, visual_info_list + i, 0, + True /* Direct rendering */); + } + + XFree(visual_info_list); + if (!context) { + return NULL; + } + + if (!glXMakeCurrent(display, window, context)) { + glXDestroyContext(display, context); + return NULL; + } + + if (glewInit() != GLEW_OK) { + LOG(ERROR) << "GLEW failed initialization"; + glXDestroyContext(display, context); + return NULL; + } + + if (!glewIsSupported("GL_VERSION_2_0")) { + LOG(ERROR) << "GL implementation doesn't support GL version 2.0"; + glXDestroyContext(display, context); + return NULL; + } + + return context; +} + +// Matrix used for the YUV to RGB conversion. +static const float kYUV2RGB[9] = { + 1.f, 0.f, 1.403f, + 1.f, -.344f, -.714f, + 1.f, 1.772f, 0.f, +}; + +// Vertices for a full screen quad. +static const float kVertices[8] = { + -1.f, 1.f, + -1.f, -1.f, + 1.f, 1.f, + 1.f, -1.f, +}; + +// Texture Coordinates mapping the entire texture. +static const float kTextureCoords[8] = { + 0, 0, + 0, 1, + 1, 0, + 1, 1, +}; + +// Pass-through vertex shader. +static const char kVertexShader[] = + "varying vec2 interp_tc;\n" + "\n" + "attribute vec4 in_pos;\n" + "attribute vec2 in_tc;\n" + "\n" + "void main() {\n" + " interp_tc = in_tc;\n" + " gl_Position = in_pos;\n" + "}\n"; + +// YUV to RGB pixel shader. Loads a pixel from each plane and pass through the +// matrix. +static const char kFragmentShader[] = + "varying vec2 interp_tc;\n" + "\n" + "uniform sampler2D y_tex;\n" + "uniform sampler2D u_tex;\n" + "uniform sampler2D v_tex;\n" + "uniform mat3 yuv2rgb;\n" + "\n" + "void main() {\n" + " float y = texture2D(y_tex, interp_tc).x;\n" + " float u = texture2D(u_tex, interp_tc).r - .5;\n" + " float v = texture2D(v_tex, interp_tc).r - .5;\n" + " vec3 rgb = yuv2rgb * vec3(y, u, v);\n" + " gl_FragColor = vec4(rgb, 1);\n" + "}\n"; + +// Buffer size for compile errors. +static const unsigned int kErrorSize = 4096; + +bool GlVideoRenderer::OnInitialize(media::VideoDecoder* decoder) { + if (!ParseMediaFormat(decoder->media_format(), &width_, &height_)) + return false; + + LOG(INFO) << "Initializing GL Renderer..."; + + // Resize the window to fit that of the video. + XResizeWindow(display_, window_, width_, height_); + + gl_context_ = InitGLContext(display_, window_); + if (!gl_context_) + return false; + + glMatrixMode(GL_MODELVIEW); + + // Create 3 textures, one for each plane, and bind them to different + // texture units. + glGenTextures(media::VideoSurface::kNumYUVPlanes, textures_); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures_[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEnable(GL_TEXTURE_2D); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEnable(GL_TEXTURE_2D); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, textures_[2]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEnable(GL_TEXTURE_2D); + + GLuint program_ = glCreateProgram(); + + // Create our YUV->RGB shader. + GLuint vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); + const char* vs_source = kVertexShader; + int vs_size = sizeof(kVertexShader); + glShaderSource(vertex_shader_, 1, &vs_source, &vs_size); + glCompileShader(vertex_shader_); + int result = GL_FALSE; + glGetShaderiv(vertex_shader_, GL_COMPILE_STATUS, &result); + if (!result) { + char log[kErrorSize]; + int len; + glGetShaderInfoLog(vertex_shader_, kErrorSize - 1, &len, log); + log[kErrorSize - 1] = 0; + LOG(FATAL) << log; + } + glAttachShader(program_, vertex_shader_); + + GLuint fragment_shader_ = glCreateShader(GL_FRAGMENT_SHADER); + const char* ps_source = kFragmentShader; + int ps_size = sizeof(kFragmentShader); + glShaderSource(fragment_shader_, 1, &ps_source, &ps_size); + glCompileShader(fragment_shader_); + result = GL_FALSE; + glGetShaderiv(fragment_shader_, GL_COMPILE_STATUS, &result); + if (!result) { + char log[kErrorSize]; + int len; + glGetShaderInfoLog(fragment_shader_, kErrorSize - 1, &len, log); + log[kErrorSize - 1] = 0; + LOG(FATAL) << log; + } + glAttachShader(program_, fragment_shader_); + + glLinkProgram(program_); + result = GL_FALSE; + glGetProgramiv(program_, GL_LINK_STATUS, &result); + if (!result) { + char log[kErrorSize]; + int len; + glGetProgramInfoLog(program_, kErrorSize - 1, &len, log); + log[kErrorSize - 1] = 0; + LOG(FATAL) << log; + } + glUseProgram(program_); + + // Bind parameters. + glUniform1i(glGetUniformLocation(program_, "y_tex"), 0); + glUniform1i(glGetUniformLocation(program_, "u_tex"), 1); + glUniform1i(glGetUniformLocation(program_, "v_tex"), 2); + int yuv2rgb_location = glGetUniformLocation(program_, "yuv2rgb"); + glUniformMatrix3fv(yuv2rgb_location, 1, GL_TRUE, kYUV2RGB); + + int pos_location = glGetAttribLocation(program_, "in_pos"); + glEnableVertexAttribArray(pos_location); + glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); + + int tc_location = glGetAttribLocation(program_, "in_tc"); + glEnableVertexAttribArray(tc_location); + glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, + kTextureCoords); + + // We are getting called on a thread. Release the context so that it can be + // made current on the main thread. + glXMakeCurrent(display_, 0, NULL); + + // Save this instance. + DCHECK(!instance_); + instance_ = this; + return true; +} + +void GlVideoRenderer::OnFrameAvailable() { + AutoLock auto_lock(lock_); + new_frame_ = true; +} + +void GlVideoRenderer::Paint() { + // Use |new_frame_| to prevent overdraw since Paint() is called more + // often than needed. It is OK to lock only this flag and we don't + // want to lock the whole function because this method takes a long + // time to complete. + { + AutoLock auto_lock(lock_); + if (!new_frame_) + return; + new_frame_ = false; + } + + scoped_refptr<media::VideoFrame> video_frame; + GetCurrentFrame(&video_frame); + + if (!video_frame) + return; + + // Convert YUV frame to RGB. + media::VideoSurface frame_in; + if (video_frame->Lock(&frame_in)) { + DCHECK(frame_in.format == media::VideoSurface::YV12 || + frame_in.format == media::VideoSurface::YV16); + DCHECK(frame_in.strides[media::VideoSurface::kUPlane] == + frame_in.strides[media::VideoSurface::kVPlane]); + DCHECK(frame_in.planes == media::VideoSurface::kNumYUVPlanes); + + if (glXGetCurrentContext() != gl_context_ || + glXGetCurrentDrawable() != window_) { + glXMakeCurrent(display_, window_, gl_context_); + } + for (unsigned int i = 0; i < media::VideoSurface::kNumYUVPlanes; ++i) { + unsigned int width = (i == media::VideoSurface::kYPlane) ? + frame_in.width : frame_in.width / 2; + unsigned int height = (i == media::VideoSurface::kYPlane || + frame_in.format == media::VideoSurface::YV16) ? + frame_in.height : frame_in.height / 2; + glActiveTexture(GL_TEXTURE0 + i); + glPixelStorei(GL_UNPACK_ROW_LENGTH, frame_in.strides[i]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, frame_in.data[i]); + } + video_frame->Unlock(); + } else { + NOTREACHED(); + } + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + glXSwapBuffers(display_, window_); +} diff --git a/media/tools/player_x11/gl_video_renderer.h b/media/tools/player_x11/gl_video_renderer.h new file mode 100644 index 0000000..21d6aaf --- /dev/null +++ b/media/tools/player_x11/gl_video_renderer.h @@ -0,0 +1,72 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +#ifndef MEDIA_TOOLS_PLAYER_X11_GL_VIDEO_RENDERER_H_ +#define MEDIA_TOOLS_PLAYER_X11_GL_VIDEO_RENDERER_H_ + +#include <GL/glew.h> +#include <GL/glxew.h> + +#include "base/lock.h" +#include "base/scoped_ptr.h" +#include "media/base/factory.h" +#include "media/filters/video_renderer_base.h" + +class GlVideoRenderer : public media::VideoRendererBase { + public: + static media::FilterFactory* CreateFactory(Display* display, + Window window) { + return new media::FilterFactoryImpl2< + GlVideoRenderer, Display*, Window>(display, window); + } + + GlVideoRenderer(Display* display, Window window); + + // This method is called to paint the current video frame to the assigned + // window. + void Paint(); + + // media::FilterFactoryImpl2 Implementation. + static bool IsMediaFormatSupported(const media::MediaFormat& media_format); + + static GlVideoRenderer* instance() { return instance_; } + + protected: + // VideoRendererBase implementation. + virtual bool OnInitialize(media::VideoDecoder* decoder); + virtual void OnStop(); + virtual void OnFrameAvailable(); + + private: + // Only allow to be deleted by reference counting. + friend class scoped_refptr<GlVideoRenderer>; + virtual ~GlVideoRenderer(); + + int width_; + int height_; + + Display* display_; + Window window_; + + // Protects |new_frame_|. + Lock lock_; + bool new_frame_; + + // GL context. + GLXContext gl_context_; + + // 3 textures, one for each plane. + GLuint textures_[3]; + + // Shaders and program for YUV->RGB conversion. + GLuint vertex_shader_; + GLuint fragment_shader_; + GLuint program_; + + static GlVideoRenderer* instance_; + + DISALLOW_COPY_AND_ASSIGN(GlVideoRenderer); +}; + +#endif // MEDIA_TOOLS_PLAYER_X11_GL_VIDEO_RENDERER_H_ diff --git a/media/tools/player_x11/gles_video_renderer.cc b/media/tools/player_x11/gles_video_renderer.cc new file mode 100644 index 0000000..601be1d --- /dev/null +++ b/media/tools/player_x11/gles_video_renderer.cc @@ -0,0 +1,344 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/tools/player_x11/gles_video_renderer.h" + +#include <dlfcn.h> +#include <X11/Xutil.h> +#include <X11/extensions/Xrender.h> +#include <X11/extensions/Xcomposite.h> + +#include "media/base/buffers.h" +#include "media/base/yuv_convert.h" + +GlesVideoRenderer* GlesVideoRenderer::instance_ = NULL; + +GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window) + : display_(display), + window_(window), + new_frame_(false), + egl_display_(NULL), + egl_surface_(NULL), + egl_context_(NULL) { +} + +GlesVideoRenderer::~GlesVideoRenderer() { +} + +// static +bool GlesVideoRenderer::IsMediaFormatSupported( + const media::MediaFormat& media_format) { + int width = 0; + int height = 0; + return ParseMediaFormat(media_format, &width, &height); +} + +void GlesVideoRenderer::OnStop() { + eglMakeCurrent(egl_display_, EGL_NO_SURFACE, + EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(egl_display_, egl_context_); + eglDestroySurface(egl_display_, egl_surface_); +} + +// Matrix used for the YUV to RGB conversion. +static const float kYUV2RGB[9] = { + 1.f, 0.f, 1.403f, + 1.f, -.344f, -.714f, + 1.f, 1.772f, 0.f, +}; + +// Vertices for a full screen quad. +static const float kVertices[8] = { + -1.f, 1.f, + -1.f, -1.f, + 1.f, 1.f, + 1.f, -1.f, +}; + +// Texture Coordinates mapping the entire texture. +static const float kTextureCoords[8] = { + 0, 0, + 0, 1, + 1, 0, + 1, 1, +}; + +// Pass-through vertex shader. +static const char kVertexShader[] = + "precision highp float; precision highp int;\n" + "varying vec2 interp_tc;\n" + "\n" + "attribute vec4 in_pos;\n" + "attribute vec2 in_tc;\n" + "\n" + "void main() {\n" + " interp_tc = in_tc;\n" + " gl_Position = in_pos;\n" + "}\n"; + +// YUV to RGB pixel shader. Loads a pixel from each plane and pass through the +// matrix. +static const char kFragmentShader[] = + "precision mediump float; precision mediump int;\n" + "varying vec2 interp_tc;\n" + "\n" + "uniform sampler2D y_tex;\n" + "uniform sampler2D u_tex;\n" + "uniform sampler2D v_tex;\n" + "uniform mat3 yuv2rgb;\n" + "\n" + "void main() {\n" + " float y = texture2D(y_tex, interp_tc).x;\n" + " float u = texture2D(u_tex, interp_tc).r - .5;\n" + " float v = texture2D(v_tex, interp_tc).r - .5;\n" + " vec3 rgb = yuv2rgb * vec3(y, u, v);\n" + " gl_FragColor = vec4(rgb, 1);\n" + "}\n"; + +// Buffer size for compile errors. +static const unsigned int kErrorSize = 4096; + +bool GlesVideoRenderer::OnInitialize(media::VideoDecoder* decoder) { + if (!ParseMediaFormat(decoder->media_format(), &width_, &height_)) + return false; + + LOG(INFO) << "Initializing GLES Renderer..."; + + // Resize the window to fit that of the video. + XResizeWindow(display_, window_, width_, height_); + + egl_display_ = eglGetDisplay(display_); + if (eglGetError() != EGL_SUCCESS) { + DLOG(ERROR) << "eglGetDisplay failed."; + return false; + } + + EGLint major; + EGLint minor; + if (!eglInitialize(egl_display_, &major, &minor)) { + DLOG(ERROR) << "eglInitialize failed."; + return false; + } + DLOG(INFO) << "EGL vendor:" << eglQueryString(egl_display_, EGL_VENDOR); + DLOG(INFO) << "EGL version:" << eglQueryString(egl_display_, EGL_VERSION); + DLOG(INFO) << "EGL extensions:" + << eglQueryString(egl_display_, EGL_EXTENSIONS); + DLOG(INFO) << "EGL client apis:" + << eglQueryString(egl_display_, EGL_CLIENT_APIS); + + EGLint attribs[] = { + EGL_RED_SIZE, 5, + EGL_GREEN_SIZE, 6, + EGL_BLUE_SIZE, 5, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 0, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_NONE + }; + + EGLint num_configs = -1; + if (!eglGetConfigs(egl_display_, NULL, 0, &num_configs)) { + DLOG(ERROR) << "eglGetConfigs failed."; + return false; + } + + EGLConfig config; + if (!eglChooseConfig(egl_display_, attribs, &config, 1, &num_configs)) { + DLOG(ERROR) << "eglChooseConfig failed."; + return false; + } + + EGLint red_size, green_size, blue_size, alpha_size, depth_size, stencil_size; + eglGetConfigAttrib(egl_display_, config, EGL_RED_SIZE, &red_size); + eglGetConfigAttrib(egl_display_, config, EGL_GREEN_SIZE, &green_size); + eglGetConfigAttrib(egl_display_, config, EGL_BLUE_SIZE, &blue_size); + eglGetConfigAttrib(egl_display_, config, EGL_ALPHA_SIZE, &alpha_size); + eglGetConfigAttrib(egl_display_, config, EGL_DEPTH_SIZE, &depth_size); + eglGetConfigAttrib(egl_display_, config, EGL_STENCIL_SIZE, &stencil_size); + DLOG(INFO) << "R,G,B,A: " << red_size << "," << green_size + << "," << blue_size << "," << alpha_size << " bits"; + DLOG(INFO) << "Depth: " << depth_size << " bits, Stencil:" << stencil_size + << "bits"; + + egl_surface_ = eglCreateWindowSurface(egl_display_, config, window_, NULL); + if (!egl_surface_) { + DLOG(ERROR) << "eglCreateWindowSurface failed."; + return false; + } + + egl_context_ = eglCreateContext(egl_display_, config, NULL, NULL); + if (!egl_context_) { + DLOG(ERROR) << "eglCreateContext failed."; + eglDestroySurface(egl_display_, egl_surface_); + return false; + } + + if (eglMakeCurrent(egl_display_, egl_surface_, + egl_surface_, egl_context_) == EGL_FALSE) { + eglDestroyContext(egl_display_, egl_context_); + eglDestroySurface(egl_display_, egl_surface_); + egl_display_ = NULL; + egl_surface_ = NULL; + egl_context_ = NULL; + return false; + } + + EGLint width; + EGLint height; + eglQuerySurface(egl_display_, egl_surface_, EGL_WIDTH, &width); + eglQuerySurface(egl_display_, egl_surface_, EGL_HEIGHT, &height); + glViewport(0, 0, width, height); + + glViewport(0, 0, width_, height_); + + // Create 3 textures, one for each plane, and bind them to different + // texture units. + glGenTextures(media::VideoSurface::kNumYUVPlanes, textures_); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, textures_[0]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEnable(GL_TEXTURE_2D); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, textures_[1]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEnable(GL_TEXTURE_2D); + + glActiveTexture(GL_TEXTURE2); + glBindTexture(GL_TEXTURE_2D, textures_[2]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glEnable(GL_TEXTURE_2D); + + GLuint program_ = glCreateProgram(); + + // Create our YUV->RGB shader. + GLuint vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); + const char* vs_source = kVertexShader; + int vs_size = sizeof(kVertexShader); + glShaderSource(vertex_shader_, 1, &vs_source, &vs_size); + glCompileShader(vertex_shader_); + int result = GL_FALSE; + glGetShaderiv(vertex_shader_, GL_COMPILE_STATUS, &result); + if (!result) { + char log[kErrorSize]; + int len; + glGetShaderInfoLog(vertex_shader_, kErrorSize - 1, &len, log); + log[kErrorSize - 1] = 0; + LOG(FATAL) << log; + } + glAttachShader(program_, vertex_shader_); + + GLuint fragment_shader_ = glCreateShader(GL_FRAGMENT_SHADER); + const char* ps_source = kFragmentShader; + int ps_size = sizeof(kFragmentShader); + glShaderSource(fragment_shader_, 1, &ps_source, &ps_size); + glCompileShader(fragment_shader_); + result = GL_FALSE; + glGetShaderiv(fragment_shader_, GL_COMPILE_STATUS, &result); + if (!result) { + char log[kErrorSize]; + int len; + glGetShaderInfoLog(fragment_shader_, kErrorSize - 1, &len, log); + log[kErrorSize - 1] = 0; + LOG(FATAL) << log; + } + glAttachShader(program_, fragment_shader_); + + glLinkProgram(program_); + result = GL_FALSE; + glGetProgramiv(program_, GL_LINK_STATUS, &result); + if (!result) { + char log[kErrorSize]; + int len; + glGetProgramInfoLog(program_, kErrorSize - 1, &len, log); + log[kErrorSize - 1] = 0; + LOG(FATAL) << log; + } + glUseProgram(program_); + + // Bind parameters. + glUniform1i(glGetUniformLocation(program_, "y_tex"), 0); + glUniform1i(glGetUniformLocation(program_, "u_tex"), 1); + glUniform1i(glGetUniformLocation(program_, "v_tex"), 2); + int yuv2rgb_location = glGetUniformLocation(program_, "yuv2rgb"); + glUniformMatrix3fv(yuv2rgb_location, 1, GL_TRUE, kYUV2RGB); + + int pos_location = glGetAttribLocation(program_, "in_pos"); + glEnableVertexAttribArray(pos_location); + glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); + + int tc_location = glGetAttribLocation(program_, "in_tc"); + glEnableVertexAttribArray(tc_location); + glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, + kTextureCoords); + + // We are getting called on a thread. Release the context so that it can be + // made current on the main thread. + eglMakeCurrent(egl_display_, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + // Save this instance. + DCHECK(!instance_); + instance_ = this; + return true; +} + +void GlesVideoRenderer::OnFrameAvailable() { + AutoLock auto_lock(lock_); + new_frame_ = true; +} + +void GlesVideoRenderer::Paint() { + // Use |new_frame_| to prevent overdraw since Paint() is called more + // often than needed. It is OK to lock only this flag and we don't + // want to lock the whole function because this method takes a long + // time to complete. + { + AutoLock auto_lock(lock_); + if (!new_frame_) + return; + new_frame_ = false; + } + + scoped_refptr<media::VideoFrame> video_frame; + GetCurrentFrame(&video_frame); + + if (!video_frame) + return; + + // Convert YUV frame to RGB. + media::VideoSurface frame_in; + if (video_frame->Lock(&frame_in)) { + DCHECK(frame_in.format == media::VideoSurface::YV12 || + frame_in.format == media::VideoSurface::YV16); + DCHECK(frame_in.strides[media::VideoSurface::kUPlane] == + frame_in.strides[media::VideoSurface::kVPlane]); + DCHECK(frame_in.planes == media::VideoSurface::kNumYUVPlanes); + + if (eglGetCurrentContext() != egl_context_) { + eglMakeCurrent(egl_display_, egl_surface_, + egl_surface_, egl_context_); + } + for (unsigned int i = 0; i < media::VideoSurface::kNumYUVPlanes; ++i) { + unsigned int width = (i == media::VideoSurface::kYPlane) ? + frame_in.width : frame_in.width / 2; + unsigned int height = (i == media::VideoSurface::kYPlane || + frame_in.format == media::VideoSurface::YV16) ? + frame_in.height : frame_in.height / 2; + glActiveTexture(GL_TEXTURE0 + i); + // No GL_UNPACK_ROW_LENGTH in GLES2. + // glPixelStorei(GL_UNPACK_ROW_LENGTH, frame_in.strides[i]); + glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, + GL_LUMINANCE, GL_UNSIGNED_BYTE, frame_in.data[i]); + } + video_frame->Unlock(); + } else { + NOTREACHED(); + } + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); + eglSwapBuffers(egl_display_, egl_surface_); +} diff --git a/media/tools/player_x11/gles_video_renderer.h b/media/tools/player_x11/gles_video_renderer.h new file mode 100644 index 0000000..ac4cd39 --- /dev/null +++ b/media/tools/player_x11/gles_video_renderer.h @@ -0,0 +1,75 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. Use of this +// source code is governed by a BSD-style license that can be found in the +// LICENSE file. + +#ifndef MEDIA_TOOLS_PLAYER_X11_GL_VIDEO_RENDERER_H_ +#define MEDIA_TOOLS_PLAYER_X11_GL_VIDEO_RENDERER_H_ + +#include <EGL/egl.h> +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#include "base/lock.h" +#include "base/scoped_ptr.h" +#include "media/base/factory.h" +#include "media/filters/video_renderer_base.h" + +class GlesVideoRenderer : public media::VideoRendererBase { + public: + static media::FilterFactory* CreateFactory(Display* display, + Window window) { + return new media::FilterFactoryImpl2< + GlesVideoRenderer, Display*, Window>(display, window); + } + + GlesVideoRenderer(Display* display, Window window); + + // This method is called to paint the current video frame to the assigned + // window. + void Paint(); + + // media::FilterFactoryImpl2 Implementation. + static bool IsMediaFormatSupported(const media::MediaFormat& media_format); + + static GlesVideoRenderer* instance() { return instance_; } + + protected: + // VideoRendererBase implementation. + virtual bool OnInitialize(media::VideoDecoder* decoder); + virtual void OnStop(); + virtual void OnFrameAvailable(); + + private: + // Only allow to be deleted by reference counting. + friend class scoped_refptr<GlesVideoRenderer>; + virtual ~GlesVideoRenderer(); + + int width_; + int height_; + + Display* display_; + Window window_; + + // Protects |new_frame_|. + Lock lock_; + bool new_frame_; + + // EGL context. + EGLDisplay egl_display_; + EGLSurface egl_surface_; + EGLContext egl_context_; + + // 3 textures, one for each plane. + GLuint textures_[3]; + + // Shaders and program for YUV->RGB conversion. + GLuint vertex_shader_; + GLuint fragment_shader_; + GLuint program_; + + static GlesVideoRenderer* instance_; + + DISALLOW_COPY_AND_ASSIGN(GlesVideoRenderer); +}; + +#endif // MEDIA_TOOLS_PLAYER_X11_GLES_VIDEO_RENDERER_H_ diff --git a/media/tools/player_x11/player_x11.cc b/media/tools/player_x11/player_x11.cc index aa8194b..a78c6d4 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2009-2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2010 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -21,7 +21,17 @@ #include "media/filters/file_data_source.h" #include "media/filters/null_audio_renderer.h" #include "media/filters/omx_video_decoder.h" + +#if defined(RENDERER_GL) +#include "media/tools/player_x11/gl_video_renderer.h" +typedef GlVideoRenderer Renderer; +#elif RENDERER_GLES +#include "media/tools/player_x11/gles_video_renderer.h" +typedef GlesVideoRenderer Renderer; +#elif RENDERER_X11 #include "media/tools/player_x11/x11_video_renderer.h" +typedef X11VideoRenderer Renderer; +#endif Display* g_display = NULL; Window g_window = 0; @@ -71,7 +81,7 @@ bool InitPipeline(MessageLoop* message_loop, factories->AddFactory(media::OmxVideoDecoder::CreateFactory()); } factories->AddFactory(media::FFmpegVideoDecoder::CreateFactory()); - factories->AddFactory(X11VideoRenderer::CreateFactory(g_display, g_window)); + factories->AddFactory(Renderer::CreateFactory(g_display, g_window)); if (enable_audio) { factories->AddFactory(media::AudioRendererImpl::CreateFilterFactory()); @@ -146,8 +156,8 @@ int main(int argc, char** argv) { XNextEvent(g_display, &e); if (e.type == Expose) { // Tell the renderer to paint. - DCHECK(X11VideoRenderer::instance()); - X11VideoRenderer::instance()->Paint(); + DCHECK(Renderer::instance()); + Renderer::instance()->Paint(); } else if (e.type == ButtonPress) { // Stop the playback. break; diff --git a/media/tools/player_x11/x11_video_renderer.cc b/media/tools/player_x11/x11_video_renderer.cc index 67c6c5c..068b971 100644 --- a/media/tools/player_x11/x11_video_renderer.cc +++ b/media/tools/player_x11/x11_video_renderer.cc @@ -59,17 +59,10 @@ X11VideoRenderer::X11VideoRenderer(Display* display, Window window) image_(NULL), new_frame_(false), picture_(0), - use_render_(false), - use_gl_(false), - gl_context_(NULL) { - // Save the instance of the video renderer. - CHECK(!instance_); - instance_ = this; + use_render_(false) { } X11VideoRenderer::~X11VideoRenderer() { - CHECK(instance_); - instance_ = NULL; } // static @@ -81,265 +74,58 @@ bool X11VideoRenderer::IsMediaFormatSupported( } void X11VideoRenderer::OnStop() { - if (use_gl_) { - glXMakeCurrent(display_, 0, NULL); - glXDestroyContext(display_, gl_context_); - } if (image_) { XDestroyImage(image_); } - if (use_render_) { - XRenderFreePicture(display_, picture_); - } + XRenderFreePicture(display_, picture_); } -static GLXContext InitGLContext(Display* display, Window window) { - // Some versions of NVIDIA's GL libGL.so include a broken version of - // dlopen/dlsym, and so linking it into chrome breaks it. So we dynamically - // load it, and use glew to dynamically resolve symbols. - // See http://code.google.com/p/chromium/issues/detail?id=16800 - void* handle = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL); - if (!handle) { - LOG(ERROR) << "Could not find libGL.so.1"; - return NULL; - } - if (glxewInit() != GLEW_OK) { - LOG(ERROR) << "GLXEW failed initialization"; - return NULL; - } - - XWindowAttributes attributes; - XGetWindowAttributes(display, window, &attributes); - XVisualInfo visual_info_template; - visual_info_template.visualid = XVisualIDFromVisual(attributes.visual); - int visual_info_count = 0; - XVisualInfo* visual_info_list = XGetVisualInfo(display, VisualIDMask, - &visual_info_template, - &visual_info_count); - GLXContext context = NULL; - for (int i = 0; i < visual_info_count && !context; ++i) { - context = glXCreateContext(display, visual_info_list + i, 0, - True /* Direct rendering */); - } - - XFree(visual_info_list); - if (!context) { - return NULL; - } - - if (!glXMakeCurrent(display, window, context)) { - glXDestroyContext(display, context); - return NULL; - } - - if (glewInit() != GLEW_OK) { - LOG(ERROR) << "GLEW failed initialization"; - glXDestroyContext(display, context); - return NULL; - } - - if (!glewIsSupported("GL_VERSION_2_0")) { - LOG(ERROR) << "GL implementation doesn't support GL version 2.0"; - glXDestroyContext(display, context); - return NULL; - } - - return context; -} - -// Matrix used for the YUV to RGB conversion. -static const float kYUV2RGB[9] = { - 1.f, 0.f, 1.403f, - 1.f, -.344f, -.714f, - 1.f, 1.772f, 0.f, -}; - -// Vertices for a full screen quad. -static const float kVertices[8] = { - -1.f, 1.f, - -1.f, -1.f, - 1.f, 1.f, - 1.f, -1.f, -}; - -// Texture Coordinates mapping the entire texture. -static const float kTextureCoords[8] = { - 0, 0, - 0, 1, - 1, 0, - 1, 1, -}; - -// Pass-through vertex shader. -static const char kVertexShader[] = - "varying vec2 interp_tc;\n" - "\n" - "attribute vec4 in_pos;\n" - "attribute vec2 in_tc;\n" - "\n" - "void main() {\n" - " interp_tc = in_tc;\n" - " gl_Position = in_pos;\n" - "}\n"; - -// YUV to RGB pixel shader. Loads a pixel from each plane and pass through the -// matrix. -static const char kFragmentShader[] = - "varying vec2 interp_tc;\n" - "\n" - "uniform sampler2D y_tex;\n" - "uniform sampler2D u_tex;\n" - "uniform sampler2D v_tex;\n" - "uniform mat3 yuv2rgb;\n" - "\n" - "void main() {\n" - " float y = texture2D(y_tex, interp_tc).x;\n" - " float u = texture2D(u_tex, interp_tc).r - .5;\n" - " float v = texture2D(v_tex, interp_tc).r - .5;\n" - " vec3 rgb = yuv2rgb * vec3(y, u, v);\n" - " gl_FragColor = vec4(rgb, 1);\n" - "}\n"; - -// Buffer size for compile errors. -static const unsigned int kErrorSize = 4096; - bool X11VideoRenderer::OnInitialize(media::VideoDecoder* decoder) { if (!ParseMediaFormat(decoder->media_format(), &width_, &height_)) return false; + LOG(INFO) << "Initializing X11 Renderer..."; + // Resize the window to fit that of the video. XResizeWindow(display_, window_, width_, height_); - gl_context_ = InitGLContext(display_, window_); - use_gl_ = (gl_context_ != NULL); - - if (use_gl_) { - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - glViewport(0, 0, width_, height_); - - // Create 3 textures, one for each plane, and bind them to different - // texture units. - glGenTextures(media::VideoSurface::kNumYUVPlanes, textures_); - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, textures_[0]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEnable(GL_TEXTURE_2D); - - glActiveTexture(GL_TEXTURE1); - glBindTexture(GL_TEXTURE_2D, textures_[1]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEnable(GL_TEXTURE_2D); - - glActiveTexture(GL_TEXTURE2); - glBindTexture(GL_TEXTURE_2D, textures_[2]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glEnable(GL_TEXTURE_2D); - - GLuint program_ = glCreateProgram(); - - // Create our YUV->RGB shader. - GLuint vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); - const char* vs_source = kVertexShader; - int vs_size = sizeof(kVertexShader); - glShaderSource(vertex_shader_, 1, &vs_source, &vs_size); - glCompileShader(vertex_shader_); - int result = GL_FALSE; - glGetShaderiv(vertex_shader_, GL_COMPILE_STATUS, &result); - if (!result) { - char log[kErrorSize]; - int len; - glGetShaderInfoLog(vertex_shader_, kErrorSize - 1, &len, log); - log[kErrorSize - 1] = 0; - LOG(FATAL) << log; - } - glAttachShader(program_, vertex_shader_); - - GLuint fragment_shader_ = glCreateShader(GL_FRAGMENT_SHADER); - const char* ps_source = kFragmentShader; - int ps_size = sizeof(kFragmentShader); - glShaderSource(fragment_shader_, 1, &ps_source, &ps_size); - glCompileShader(fragment_shader_); - result = GL_FALSE; - glGetShaderiv(fragment_shader_, GL_COMPILE_STATUS, &result); - if (!result) { - char log[kErrorSize]; - int len; - glGetShaderInfoLog(fragment_shader_, kErrorSize - 1, &len, log); - log[kErrorSize - 1] = 0; - LOG(FATAL) << log; - } - glAttachShader(program_, fragment_shader_); - - glLinkProgram(program_); - result = GL_FALSE; - glGetProgramiv(program_, GL_LINK_STATUS, &result); - if (!result) { - char log[kErrorSize]; - int len; - glGetProgramInfoLog(program_, kErrorSize - 1, &len, log); - log[kErrorSize - 1] = 0; - LOG(FATAL) << log; - } - glUseProgram(program_); - - // Bind parameters. - glUniform1i(glGetUniformLocation(program_, "y_tex"), 0); - glUniform1i(glGetUniformLocation(program_, "u_tex"), 1); - glUniform1i(glGetUniformLocation(program_, "v_tex"), 2); - int yuv2rgb_location = glGetUniformLocation(program_, "yuv2rgb"); - glUniformMatrix3fv(yuv2rgb_location, 1, GL_TRUE, kYUV2RGB); - - int pos_location = glGetAttribLocation(program_, "in_pos"); - glEnableVertexAttribArray(pos_location); - glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); - - int tc_location = glGetAttribLocation(program_, "in_tc"); - glEnableVertexAttribArray(tc_location); - glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, - kTextureCoords); - - // We are getting called on a thread. Release the context so that it can be - // made current on the main thread. - glXMakeCurrent(display_, 0, NULL); - } else { - // Testing XRender support. We'll use the very basic of XRender - // so if it presents it is already good enough. We don't need - // to check its version. - int dummy; - use_render_ = XRenderQueryExtension(display_, &dummy, &dummy); - - if (use_render_) { - // If we are using XRender, we'll create a picture representing the - // window. - XWindowAttributes attr; - XGetWindowAttributes(display_, window_, &attr); - - XRenderPictFormat* pictformat = XRenderFindVisualFormat( - display_, - attr.visual); - CHECK(pictformat) << "XRENDER does not support default visual"; - - picture_ = XRenderCreatePicture(display_, window_, pictformat, 0, NULL); - CHECK(picture_) << "Backing picture not created"; - } - - // Initialize the XImage to store the output of YUV -> RGB conversion. - image_ = XCreateImage(display_, - DefaultVisual(display_, DefaultScreen(display_)), - DefaultDepth(display_, DefaultScreen(display_)), - ZPixmap, - 0, - static_cast<char*>(malloc(width_ * height_ * 4)), - width_, - height_, - 32, - width_ * 4); - DCHECK(image_); - } + // Testing XRender support. We'll use the very basic of XRender + // so if it presents it is already good enough. We don't need + // to check its version. + int dummy; + use_render_ = XRenderQueryExtension(display_, &dummy, &dummy); + + if (use_render_) { + // If we are using XRender, we'll create a picture representing the + // window. + XWindowAttributes attr; + XGetWindowAttributes(display_, window_, &attr); + + XRenderPictFormat* pictformat = XRenderFindVisualFormat( + display_, + attr.visual); + CHECK(pictformat) << "XRENDER does not support default visual"; + + picture_ = XRenderCreatePicture(display_, window_, pictformat, 0, NULL); + CHECK(picture_) << "Backing picture not created"; + } + + // Initialize the XImage to store the output of YUV -> RGB conversion. + image_ = XCreateImage(display_, + DefaultVisual(display_, DefaultScreen(display_)), + DefaultDepth(display_, DefaultScreen(display_)), + ZPixmap, + 0, + static_cast<char*>(malloc(width_ * height_ * 4)), + width_, + height_, + 32, + width_ * 4); + DCHECK(image_); + + // Save this instance. + DCHECK(!instance_); + instance_ = this; return true; } @@ -363,7 +149,7 @@ void X11VideoRenderer::Paint() { scoped_refptr<media::VideoFrame> video_frame; GetCurrentFrame(&video_frame); - if ((!use_gl_ && !image_) || !video_frame) + if (!image_ ||!video_frame) return; // Convert YUV frame to RGB. @@ -375,48 +161,24 @@ void X11VideoRenderer::Paint() { frame_in.strides[media::VideoSurface::kVPlane]); DCHECK(frame_in.planes == media::VideoSurface::kNumYUVPlanes); - if (use_gl_) { - if (glXGetCurrentContext() != gl_context_ || - glXGetCurrentDrawable() != window_) { - glXMakeCurrent(display_, window_, gl_context_); - } - for (unsigned int i = 0; i < media::VideoSurface::kNumYUVPlanes; ++i) { - unsigned int width = (i == media::VideoSurface::kYPlane) ? - frame_in.width : frame_in.width / 2; - unsigned int height = (i == media::VideoSurface::kYPlane || - frame_in.format == media::VideoSurface::YV16) ? - frame_in.height : frame_in.height / 2; - glActiveTexture(GL_TEXTURE0 + i); - glPixelStorei(GL_UNPACK_ROW_LENGTH, frame_in.strides[i]); - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, frame_in.data[i]); - } - } else { - DCHECK(image_->data); - media::YUVType yuv_type = (frame_in.format == media::VideoSurface::YV12) ? - media::YV12 : media::YV16; - media::ConvertYUVToRGB32(frame_in.data[media::VideoSurface::kYPlane], - frame_in.data[media::VideoSurface::kUPlane], - frame_in.data[media::VideoSurface::kVPlane], - (uint8*)image_->data, - frame_in.width, - frame_in.height, - frame_in.strides[media::VideoSurface::kYPlane], - frame_in.strides[media::VideoSurface::kUPlane], - image_->bytes_per_line, - yuv_type); - } + DCHECK(image_->data); + media::YUVType yuv_type = (frame_in.format == media::VideoSurface::YV12) ? + media::YV12 : media::YV16; + media::ConvertYUVToRGB32(frame_in.data[media::VideoSurface::kYPlane], + frame_in.data[media::VideoSurface::kUPlane], + frame_in.data[media::VideoSurface::kVPlane], + (uint8*)image_->data, + frame_in.width, + frame_in.height, + frame_in.strides[media::VideoSurface::kYPlane], + frame_in.strides[media::VideoSurface::kUPlane], + image_->bytes_per_line, + yuv_type); video_frame->Unlock(); } else { NOTREACHED(); } - if (use_gl_) { - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - glXSwapBuffers(display_, window_); - return; - } - if (use_render_) { // If XRender is used, we'll upload the image to a pixmap. And then // creats a picture from the pixmap and composite the picture over diff --git a/media/tools/player_x11/x11_video_renderer.h b/media/tools/player_x11/x11_video_renderer.h index ed94e6d..2b17eec 100644 --- a/media/tools/player_x11/x11_video_renderer.h +++ b/media/tools/player_x11/x11_video_renderer.h @@ -5,8 +5,6 @@ #ifndef MEDIA_TOOLS_PLAYER_X11_X11_VIDEO_RENDERER_H_ #define MEDIA_TOOLS_PLAYER_X11_X11_VIDEO_RENDERER_H_ -#include <GL/glew.h> -#include <GL/glxew.h> #include <X11/Xlib.h> #include "base/lock.h" @@ -31,7 +29,6 @@ class X11VideoRenderer : public media::VideoRendererBase { // media::FilterFactoryImpl2 Implementation. static bool IsMediaFormatSupported(const media::MediaFormat& media_format); - // Returns the instance of this class. static X11VideoRenderer* instance() { return instance_; } protected: @@ -64,19 +61,6 @@ class X11VideoRenderer : public media::VideoRendererBase { bool use_render_; - bool use_gl_; - - // GL context. - GLXContext gl_context_; - - // 3 textures, one for each plane. - GLuint textures_[3]; - - // Shaders and program for YUV->RGB conversion. - GLuint vertex_shader_; - GLuint fragment_shader_; - GLuint program_; - static X11VideoRenderer* instance_; DISALLOW_COPY_AND_ASSIGN(X11VideoRenderer); |