diff options
author | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-19 19:13:12 +0000 |
---|---|---|
committer | scherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-07-19 19:13:12 +0000 |
commit | a7fee967599ebc2bf996aba2c42b9257a5c29e68 (patch) | |
tree | 15dab1de10b5b2542d23e283864260d0ea400d2a /media | |
parent | ba412b9f51c8367c6a7baa2ace212ddeb1159137 (diff) | |
download | chromium_src-a7fee967599ebc2bf996aba2c42b9257a5c29e68.zip chromium_src-a7fee967599ebc2bf996aba2c42b9257a5c29e68.tar.gz chromium_src-a7fee967599ebc2bf996aba2c42b9257a5c29e68.tar.bz2 |
Remove Gles2VideoRenderer from player_x11 and make X11 vs GL rendering a run-time option.
Also removed AdaptiveDemuxer since it causes run-time checks at the moment.
Review URL: http://codereview.chromium.org/7410008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@93074 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r-- | media/media.gyp | 42 | ||||
-rw-r--r-- | media/tools/player_x11/gl_video_renderer.cc | 23 | ||||
-rw-r--r-- | media/tools/player_x11/gl_video_renderer.h | 21 | ||||
-rw-r--r-- | media/tools/player_x11/gles_video_renderer.cc | 524 | ||||
-rw-r--r-- | media/tools/player_x11/gles_video_renderer.h | 81 | ||||
-rw-r--r-- | media/tools/player_x11/player_x11.cc | 59 | ||||
-rw-r--r-- | media/tools/player_x11/x11_video_renderer.cc | 26 | ||||
-rw-r--r-- | media/tools/player_x11/x11_video_renderer.h | 19 |
8 files changed, 57 insertions, 738 deletions
diff --git a/media/media.gyp b/media/media.gyp index 025fbdf..7c3d16f 100644 --- a/media/media.gyp +++ b/media/media.gyp @@ -5,7 +5,6 @@ { 'variables': { 'chromium_code': 1, - 'player_x11_renderer%': 'x11', }, 'targets': [ { @@ -684,6 +683,7 @@ 'dependencies': [ 'media', '../base/base.gyp:base', + '../ui/gfx/gl/gl.gyp:gl', ], 'link_settings': { 'libraries': [ @@ -694,43 +694,11 @@ ], }, 'sources': [ + 'tools/player_x11/gl_video_renderer.cc', + 'tools/player_x11/gl_video_renderer.h', 'tools/player_x11/player_x11.cc', - ], - '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': [ - '../ui/gfx/gl/gl.gyp:gl', - ], - 'sources': [ - 'tools/player_x11/gl_video_renderer.cc', - 'tools/player_x11/gl_video_renderer.h', - ], - 'defines': [ - 'RENDERER_GL', - ], - }], + 'tools/player_x11/x11_video_renderer.cc', + 'tools/player_x11/x11_video_renderer.h', ], }, ], diff --git a/media/tools/player_x11/gl_video_renderer.cc b/media/tools/player_x11/gl_video_renderer.cc index 590f39a..e39d1dd 100644 --- a/media/tools/player_x11/gl_video_renderer.cc +++ b/media/tools/player_x11/gl_video_renderer.cc @@ -6,23 +6,21 @@ #include <X11/Xutil.h> +#include "base/message_loop.h" #include "media/base/buffers.h" #include "media/base/video_frame.h" #include "media/base/yuv_convert.h" #include "ui/gfx/gl/gl_implementation.h" -GlVideoRenderer* GlVideoRenderer::instance_ = NULL; - GlVideoRenderer::GlVideoRenderer(Display* display, Window window, - MessageLoop* message_loop) + MessageLoop* main_message_loop) : display_(display), window_(window), gl_context_(NULL), - glx_thread_message_loop_(message_loop) { + main_message_loop_(main_message_loop) { } -GlVideoRenderer::~GlVideoRenderer() { -} +GlVideoRenderer::~GlVideoRenderer() {} void GlVideoRenderer::OnStop(media::FilterCallback* callback) { glXMakeCurrent(display_, 0, NULL); @@ -227,20 +225,17 @@ bool GlVideoRenderer::OnInitialize(media::VideoDecoder* decoder) { // made current on the main thread. glXMakeCurrent(display_, 0, NULL); - // Save this instance. - DCHECK(!instance_); - instance_ = this; return true; } void GlVideoRenderer::OnFrameAvailable() { - if (glx_thread_message_loop()) { - glx_thread_message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, &GlVideoRenderer::Paint)); - } + main_message_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &GlVideoRenderer::PaintOnMainThread)); } -void GlVideoRenderer::Paint() { +void GlVideoRenderer::PaintOnMainThread() { + DCHECK_EQ(main_message_loop_, MessageLoop::current()); + scoped_refptr<media::VideoFrame> video_frame; GetCurrentFrame(&video_frame); diff --git a/media/tools/player_x11/gl_video_renderer.h b/media/tools/player_x11/gl_video_renderer.h index 01fcdbf..9d816f7 100644 --- a/media/tools/player_x11/gl_video_renderer.h +++ b/media/tools/player_x11/gl_video_renderer.h @@ -6,23 +6,15 @@ #define MEDIA_TOOLS_PLAYER_X11_GL_VIDEO_RENDERER_H_ #include "base/memory/scoped_ptr.h" -#include "media/base/filters.h" #include "media/filters/video_renderer_base.h" #include "ui/gfx/gl/gl_bindings.h" +class MessageLoop; + class GlVideoRenderer : public media::VideoRendererBase { public: - GlVideoRenderer(Display* display, Window window, MessageLoop* message_loop); - - // This method is called to paint the current video frame to the assigned - // window. - void Paint(); - - static GlVideoRenderer* instance() { return instance_; } - - MessageLoop* glx_thread_message_loop() { - return glx_thread_message_loop_; - } + GlVideoRenderer(Display* display, Window window, + MessageLoop* main_message_loop); protected: // VideoRendererBase implementation. @@ -35,6 +27,8 @@ class GlVideoRenderer : public media::VideoRendererBase { friend class scoped_refptr<GlVideoRenderer>; virtual ~GlVideoRenderer(); + void PaintOnMainThread(); + Display* display_; Window window_; @@ -44,8 +38,7 @@ class GlVideoRenderer : public media::VideoRendererBase { // 3 textures, one for each plane. GLuint textures_[3]; - MessageLoop* glx_thread_message_loop_; - static GlVideoRenderer* instance_; + MessageLoop* main_message_loop_; DISALLOW_COPY_AND_ASSIGN(GlVideoRenderer); }; diff --git a/media/tools/player_x11/gles_video_renderer.cc b/media/tools/player_x11/gles_video_renderer.cc deleted file mode 100644 index 3ccc065..0000000 --- a/media/tools/player_x11/gles_video_renderer.cc +++ /dev/null @@ -1,524 +0,0 @@ -// 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 <EGL/eglext.h> -#include <X11/Xutil.h> -#include <X11/extensions/Xrender.h> -#include <X11/extensions/Xcomposite.h> - -#include "media/base/buffers.h" -#include "media/base/filter_host.h" -#include "media/base/pipeline.h" -#include "media/base/video_frame.h" -#include "media/base/yuv_convert.h" - -GlesVideoRenderer* GlesVideoRenderer::instance_ = NULL; - -// TODO(vmr): Refactor this parameter to work either through environment -// variable or dynamically sniff whether EGL support is available. -static inline int uses_egl_image() { - return 1; -} - -GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window, - MessageLoop* message_loop) - : egl_create_image_khr_(NULL), - egl_destroy_image_khr_(NULL), - display_(display), - window_(window), - egl_display_(NULL), - egl_surface_(NULL), - egl_context_(NULL), - glx_thread_message_loop_(message_loop) { -} - -GlesVideoRenderer::~GlesVideoRenderer() { -} - -void GlesVideoRenderer::OnStop(media::FilterCallback* callback) { - if (glx_thread_message_loop()) { - glx_thread_message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, &GlesVideoRenderer::DeInitializeGlesTask, - callback)); - } -} - -void GlesVideoRenderer::DeInitializeGlesTask(media::FilterCallback* callback) { - DCHECK_EQ(glx_thread_message_loop(), MessageLoop::current()); - - for (size_t i = 0; i < egl_frames_.size(); ++i) { - scoped_refptr<media::VideoFrame> frame = egl_frames_[i].first; - if (frame->private_buffer()) - egl_destroy_image_khr_(egl_display_, frame->private_buffer()); - if (egl_frames_[i].second) - glDeleteTextures(1, &egl_frames_[i].second); - } - egl_frames_.clear(); - eglMakeCurrent(egl_display_, EGL_NO_SURFACE, - EGL_NO_SURFACE, EGL_NO_CONTEXT); - eglDestroyContext(egl_display_, egl_context_); - eglDestroySurface(egl_display_, egl_surface_); - - if (callback) { - callback->Run(); - delete callback; - } -} - -// Matrix used for the YUV to RGB conversion. -static const float kYUV2RGB[9] = { - 1.f, 1.f, 1.f, - 0.f, -.344f, 1.772f, - 1.403f, -.714f, 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, -}; - -// Texture Coordinates mapping the entire texture for EGL image. -static const float kTextureCoordsEgl[8] = { - 0, 1, - 0, 0, - 1, 1, - 1, 0, -}; - -// 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" - "uniform float half;\n" - "\n" - "void main() {\n" - " float y = texture2D(y_tex, interp_tc).x;\n" - " float u = texture2D(u_tex, interp_tc).r - half;\n" - " float v = texture2D(v_tex, interp_tc).r - half;\n" - " vec3 rgb = yuv2rgb * vec3(y, u, v);\n" - " gl_FragColor = vec4(rgb, 1);\n" - "}\n"; - -// Color shader for EGLImage. -static const char kFragmentShaderEgl[] = - "precision mediump float;\n" - "precision mediump int;\n" - "varying vec2 interp_tc;\n" - "\n" - "uniform sampler2D tex;\n" - "\n" - "void main() {\n" - " gl_FragColor = texture2D(tex, interp_tc);\n" - "}\n"; - -// Buffer size for compile errors. -static const unsigned int kErrorSize = 4096; - -bool GlesVideoRenderer::OnInitialize(media::VideoDecoder* decoder) { - LOG(INFO) << "Initializing GLES Renderer..."; - - // Save this instance. - DCHECK(!instance_); - instance_ = this; - return true; -} - -void GlesVideoRenderer::OnFrameAvailable() { - if (glx_thread_message_loop()) { - glx_thread_message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, &GlesVideoRenderer::Paint)); - } -} - -void GlesVideoRenderer::Paint() { - // Initialize GLES here to avoid context switching. Some drivers doesn't - // like switching context between threads. - static bool initialized = false; - if (!initialized && !InitializeGles()) { - initialized = true; - host()->SetError(media::PIPELINE_ERROR_COULD_NOT_RENDER); - return; - } - initialized = true; - - scoped_refptr<media::VideoFrame> video_frame; - GetCurrentFrame(&video_frame); - if (!video_frame.get()) { - PutCurrentFrame(video_frame); - return; - } - - if (uses_egl_image()) { - if (media::VideoFrame::TYPE_GL_TEXTURE == video_frame->type()) { - GLuint texture = FindTexture(video_frame); - if (texture) { - glActiveTexture(GL_TEXTURE0); - glBindTexture(GL_TEXTURE_2D, texture); - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - eglSwapBuffers(egl_display_, egl_surface_); - } - } - // TODO(jiesun/wjia): use fence before call put. - PutCurrentFrame(video_frame); - return; - } - - // Convert YUV frame to RGB. - DCHECK(video_frame->format() == media::VideoFrame::YV12 || - video_frame->format() == media::VideoFrame::YV16); - DCHECK(video_frame->stride(media::VideoFrame::kUPlane) == - video_frame->stride(media::VideoFrame::kVPlane)); - DCHECK(video_frame->planes() == media::VideoFrame::kNumYUVPlanes); - - for (unsigned int i = 0; i < media::VideoFrame::kNumYUVPlanes; ++i) { - unsigned int width = (i == media::VideoFrame::kYPlane) ? - video_frame->width() : video_frame->width() / 2; - unsigned int height = (i == media::VideoFrame::kYPlane || - video_frame->format() == media::VideoFrame::YV16) ? - video_frame->height() : video_frame->height() / 2; - glActiveTexture(GL_TEXTURE0 + i); - // GLES2 supports a fixed set of unpack alignments that should match most - // of the time what ffmpeg outputs. - // TODO(piman): check if it is more efficient to prefer higher - // alignments. - unsigned int stride = video_frame->stride(i); - uint8* data = video_frame->data(i); - if (stride == width) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 1); - } else if (stride == ((width + 1) & ~1)) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 2); - } else if (stride == ((width + 3) & ~3)) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 4); - } else if (stride == ((width + 7) & ~7)) { - glPixelStorei(GL_UNPACK_ALIGNMENT, 8); - } else { - // Otherwise do it line-by-line. - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); - for (unsigned int y = 0; y < height; ++y) { - glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, width, 1, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); - data += stride; - } - continue; - } - - glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, - GL_LUMINANCE, GL_UNSIGNED_BYTE, data); - } - PutCurrentFrame(video_frame); - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); - eglSwapBuffers(egl_display_, egl_surface_); -} - -// find if texture exists corresponding to video_frame -GLuint GlesVideoRenderer::FindTexture( - scoped_refptr<media::VideoFrame> video_frame) { - for (size_t i = 0; i < egl_frames_.size(); ++i) { - scoped_refptr<media::VideoFrame> frame = egl_frames_[i].first; - if (video_frame->private_buffer() == frame->private_buffer()) - return egl_frames_[i].second; - } - return NULL; -} - -bool GlesVideoRenderer::InitializeGles() { - // 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; - } - - EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE}; - egl_context_ = eglCreateContext(egl_display_, config, - EGL_NO_CONTEXT, context_attribs); - 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 surface_width; - EGLint surface_height; - eglQuerySurface(egl_display_, egl_surface_, EGL_WIDTH, &surface_width); - eglQuerySurface(egl_display_, egl_surface_, EGL_HEIGHT, &surface_height); - glViewport(0, 0, width(), height()); - - if (uses_egl_image()) { - CreateTextureAndProgramEgl(); - return true; - } - - CreateTextureAndProgramYuv2Rgb(); - - // We are getting called on a thread. Release the context so that it can be - // made current on the main thread. - // TODO(hclam): Fix this if neccessary. Currently the following call fails - // for some drivers. - // eglMakeCurrent(egl_display_, EGL_NO_SURFACE, - // EGL_NO_SURFACE, EGL_NO_CONTEXT); - return true; -} - -void GlesVideoRenderer::CreateShader(GLuint program, - GLenum type, - const char* source, - int size) { - GLuint shader = glCreateShader(type); - glShaderSource(shader, 1, &source, &size); - glCompileShader(shader); - int result = GL_FALSE; - glGetShaderiv(shader, GL_COMPILE_STATUS, &result); - if (!result) { - char log[kErrorSize]; - int len = 0; - glGetShaderInfoLog(shader, kErrorSize - 1, &len, log); - log[kErrorSize - 1] = 0; - LOG(FATAL) << log; - } - glAttachShader(program, shader); - glDeleteShader(shader); -} - -void GlesVideoRenderer::LinkProgram(GLuint program) { - glLinkProgram(program); - int result = GL_FALSE; - glGetProgramiv(program, GL_LINK_STATUS, &result); - if (!result) { - char log[kErrorSize]; - int len = 0; - glGetProgramInfoLog(program, kErrorSize - 1, &len, log); - log[kErrorSize - 1] = 0; - LOG(FATAL) << log; - } - glUseProgram(program); - glDeleteProgram(program); -} - -void GlesVideoRenderer::CreateTextureAndProgramEgl() { - if (!egl_create_image_khr_) - egl_create_image_khr_ = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC> - (eglGetProcAddress("eglCreateImageKHR")); - if (!egl_destroy_image_khr_) - egl_destroy_image_khr_ = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC> - (eglGetProcAddress("eglDestroyImageKHR")); - // TODO(wjia): get count from decoder. - for (int i = 0; i < 4; i++) { - GLuint texture; - EGLint attrib = EGL_NONE; - EGLImageKHR egl_image; - - glGenTextures(1, &texture); - glBindTexture(GL_TEXTURE_2D, texture); - glTexImage2D( - GL_TEXTURE_2D, - 0, - GL_RGBA, - width(), - height(), - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - NULL); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); - - egl_image = egl_create_image_khr_( - egl_display_, - egl_context_, - EGL_GL_TEXTURE_2D_KHR, - reinterpret_cast<EGLClientBuffer>(texture), - &attrib); - - scoped_refptr<media::VideoFrame> video_frame; - const base::TimeDelta kZero; - // The data/strides are not relevant in this case. - uint8* data[media::VideoFrame::kMaxPlanes]; - int32 strides[media::VideoFrame::kMaxPlanes]; - memset(data, 0, sizeof(data)); - memset(strides, 0, sizeof(strides)); - media::VideoFrame:: CreateFrameExternal( - media::VideoFrame::TYPE_GL_TEXTURE, - media::VideoFrame::RGB565, - width(), height(), 3, - data, strides, - kZero, kZero, - egl_image, - &video_frame); - egl_frames_.push_back(std::make_pair(video_frame, texture)); - ReadInput(video_frame); - } - - GLuint program = glCreateProgram(); - - // Create shader for EGL image - CreateShader(program, GL_VERTEX_SHADER, - kVertexShader, sizeof(kVertexShader)); - CreateShader(program, GL_FRAGMENT_SHADER, - kFragmentShaderEgl, sizeof(kFragmentShaderEgl)); - LinkProgram(program); - - // Bind parameters. - glUniform1i(glGetUniformLocation(program, "tex"), 0); - - 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, - kTextureCoordsEgl); -} - -void GlesVideoRenderer::CreateTextureAndProgramYuv2Rgb() { - // Create 3 textures, one for each plane, and bind them to different - // texture units. - glGenTextures(media::VideoFrame::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. - CreateShader(program, GL_VERTEX_SHADER, - kVertexShader, sizeof(kVertexShader)); - CreateShader(program, GL_FRAGMENT_SHADER, - kFragmentShader, sizeof(kFragmentShader)); - LinkProgram(program); - - // Bind parameters. - glUniform1i(glGetUniformLocation(program, "y_tex"), 0); - glUniform1i(glGetUniformLocation(program, "u_tex"), 1); - glUniform1i(glGetUniformLocation(program, "v_tex"), 2); - // WAR for some vendor's compiler issues for constant literal. - glUniform1f(glGetUniformLocation(program, "half"), 0.5); - int yuv2rgb_location = glGetUniformLocation(program, "yuv2rgb"); - glUniformMatrix3fv(yuv2rgb_location, 1, GL_FALSE, 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); -} diff --git a/media/tools/player_x11/gles_video_renderer.h b/media/tools/player_x11/gles_video_renderer.h deleted file mode 100644 index 1b70d70..0000000 --- a/media/tools/player_x11/gles_video_renderer.h +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2011 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_GLES_VIDEO_RENDERER_H_ -#define MEDIA_TOOLS_PLAYER_X11_GLES_VIDEO_RENDERER_H_ - -#include <EGL/egl.h> -#include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> - -#include <utility> -#include <vector> - -#include "base/memory/scoped_ptr.h" -#include "base/message_loop.h" -#include "media/base/filters.h" -#include "media/base/video_frame.h" -#include "media/filters/video_renderer_base.h" - -class GlesVideoRenderer : public media::VideoRendererBase { - public: - GlesVideoRenderer(Display* display, Window window, MessageLoop* message_loop); - - // This method is called to paint the current video frame to the assigned - // window. - void Paint(); - - static GlesVideoRenderer* instance() { return instance_; } - - MessageLoop* glx_thread_message_loop() { - return glx_thread_message_loop_; - } - - protected: - // VideoRendererBase implementation. - virtual bool OnInitialize(media::VideoDecoder* decoder); - virtual void OnStop(media::FilterCallback* callback); - virtual void OnFrameAvailable(); - - private: - // Only allow to be deleted by reference counting. - friend class scoped_refptr<GlesVideoRenderer>; - virtual ~GlesVideoRenderer(); - - GLuint FindTexture(scoped_refptr<media::VideoFrame> video_frame); - bool InitializeGles(); - void CreateShader(GLuint program, GLenum type, - const char* vs_source, int vs_size); - void LinkProgram(GLuint program); - void CreateTextureAndProgramEgl(); - void CreateTextureAndProgramYuv2Rgb(); - - void DeInitializeGlesTask(media::FilterCallback* callback); - - PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr_; - PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr_; - - Display* display_; - Window window_; - - // EGL context. - EGLDisplay egl_display_; - EGLSurface egl_surface_; - EGLContext egl_context_; - - // textures for EGL image - typedef std::pair<scoped_refptr<media::VideoFrame>, GLuint> EglFrame; - std::vector<EglFrame> egl_frames_; - - // 3 textures, one for each plane. - GLuint textures_[3]; - - MessageLoop* glx_thread_message_loop_; - 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 590306b..4b34a60 100644 --- a/media/tools/player_x11/player_x11.cc +++ b/media/tools/player_x11/player_x11.cc @@ -19,38 +19,18 @@ #include "media/base/media_switches.h" #include "media/base/message_loop_factory_impl.h" #include "media/base/pipeline_impl.h" -#include "media/filters/adaptive_demuxer.h" #include "media/filters/audio_renderer_impl.h" #include "media/filters/ffmpeg_audio_decoder.h" #include "media/filters/ffmpeg_demuxer_factory.h" #include "media/filters/ffmpeg_video_decoder.h" #include "media/filters/file_data_source_factory.h" #include "media/filters/null_audio_renderer.h" - -// TODO(jiesun): implement different video decode contexts according to -// these flags. e.g. -// 1. system memory video decode context for x11 -// 2. gl texture video decode context for OpenGL. -// 3. gles texture video decode context for OpenGLES. -// TODO(jiesun): add an uniform video renderer which take the video -// decode context object and delegate renderer request to these -// objects. i.e. Seperate "painter" and "pts scheduler". -#if defined(RENDERER_GL) #include "media/tools/player_x11/gl_video_renderer.h" -typedef GlVideoRenderer Renderer; -#elif defined(RENDERER_GLES) -#include "media/tools/player_x11/gles_video_renderer.h" -typedef GlesVideoRenderer Renderer; -#elif defined(RENDERER_X11) #include "media/tools/player_x11/x11_video_renderer.h" -typedef X11VideoRenderer Renderer; -#else -#error No video renderer defined. -#endif -Display* g_display = NULL; -Window g_window = 0; -bool g_running = false; +static Display* g_display = NULL; +static Window g_window = 0; +static bool g_running = false; class MessageLoopQuitter { public: @@ -90,7 +70,9 @@ bool InitX11() { } bool InitPipeline(MessageLoop* message_loop, - const char* filename, bool enable_audio, + const char* filename, + bool use_gl, + bool enable_audio, scoped_refptr<media::PipelineImpl>* pipeline, MessageLoop* paint_message_loop, media::MessageLoopFactory* message_loop_factory) { @@ -104,17 +86,21 @@ bool InitPipeline(MessageLoop* message_loop, scoped_ptr<media::FilterCollection> collection( new media::FilterCollection()); collection->SetDemuxerFactory( - new media::AdaptiveDemuxerFactory( - new media::FFmpegDemuxerFactory( - new media::FileDataSourceFactory(), message_loop))); + new media::FFmpegDemuxerFactory( + new media::FileDataSourceFactory(), message_loop)); collection->AddAudioDecoder(new media::FFmpegAudioDecoder( message_loop_factory->GetMessageLoop("AudioDecoderThread"))); collection->AddVideoDecoder(new media::FFmpegVideoDecoder( message_loop_factory->GetMessageLoop("VideoDecoderThread"), NULL)); - collection->AddVideoRenderer(new Renderer(g_display, - g_window, - paint_message_loop)); + + if (use_gl) { + collection->AddVideoRenderer( + new GlVideoRenderer(g_display, g_window, paint_message_loop)); + } else { + collection->AddVideoRenderer( + new X11VideoRenderer(g_display, g_window, paint_message_loop)); + } if (enable_audio) collection->AddAudioRenderer(new media::AudioRendererImpl()); @@ -160,13 +146,6 @@ void PeriodicalUpdate( XEvent e; XNextEvent(g_display, &e); switch (e.type) { - case Expose: - if (!audio_only) { - // Tell the renderer to paint. - DCHECK(Renderer::instance()); - Renderer::instance()->Paint(); - } - break; case ButtonPress: { Window window; @@ -219,7 +198,8 @@ int main(int argc, char** argv) { << std::endl << "Optional arguments:" << std::endl << " [--audio]" - << " [--alsa-device=DEVICE]" << std::endl + << " [--alsa-device=DEVICE]" + << " [--use-gl]" << std::endl << " Press [ESC] to stop" << std::endl << " Press [SPACE] to toggle pause/play" << std::endl << " Press mouse left button to seek" << std::endl; @@ -231,6 +211,7 @@ int main(int argc, char** argv) { std::string filename = CommandLine::ForCurrentProcess()->GetSwitchValueASCII("file"); bool enable_audio = CommandLine::ForCurrentProcess()->HasSwitch("audio"); + bool use_gl = CommandLine::ForCurrentProcess()->HasSwitch("use-gl"); bool audio_only = false; logging::InitLogging( @@ -258,7 +239,7 @@ int main(int argc, char** argv) { thread.reset(new base::Thread("PipelineThread")); thread->Start(); if (InitPipeline(thread->message_loop(), filename.c_str(), - enable_audio, &pipeline, &message_loop, + use_gl, enable_audio, &pipeline, &message_loop, message_loop_factory.get())) { // Main loop of the application. g_running = true; diff --git a/media/tools/player_x11/x11_video_renderer.cc b/media/tools/player_x11/x11_video_renderer.cc index 2c50e50..9633303 100644 --- a/media/tools/player_x11/x11_video_renderer.cc +++ b/media/tools/player_x11/x11_video_renderer.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Copyright (c) 2011 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. @@ -13,8 +13,6 @@ #include "media/base/video_frame.h" #include "media/base/yuv_convert.h" -X11VideoRenderer* X11VideoRenderer::instance_ = NULL; - // Returns the picture format for ARGB. // This method is originally from chrome/common/x11_util.cc. static XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { @@ -55,17 +53,16 @@ static XRenderPictFormat* GetRenderARGB32Format(Display* dpy) { } X11VideoRenderer::X11VideoRenderer(Display* display, Window window, - MessageLoop* message_loop) + MessageLoop* main_message_loop) : display_(display), window_(window), image_(NULL), picture_(0), use_render_(false), - glx_thread_message_loop_(message_loop) { + main_message_loop_(main_message_loop) { } -X11VideoRenderer::~X11VideoRenderer() { -} +X11VideoRenderer::~X11VideoRenderer() {} void X11VideoRenderer::OnStop(media::FilterCallback* callback) { if (image_) { @@ -91,6 +88,8 @@ bool X11VideoRenderer::OnInitialize(media::VideoDecoder* decoder) { use_render_ = XRenderQueryExtension(display_, &dummy, &dummy); if (use_render_) { + LOG(INFO) << "Using XRender extension."; + // If we are using XRender, we'll create a picture representing the // window. XWindowAttributes attr; @@ -118,20 +117,17 @@ bool X11VideoRenderer::OnInitialize(media::VideoDecoder* decoder) { width() * 4); DCHECK(image_); - // Save this instance. - DCHECK(!instance_); - instance_ = this; return true; } void X11VideoRenderer::OnFrameAvailable() { - if (glx_thread_message_loop()) { - glx_thread_message_loop()->PostTask(FROM_HERE, - NewRunnableMethod(this, &X11VideoRenderer::Paint)); - } + main_message_loop_->PostTask(FROM_HERE, + NewRunnableMethod(this, &X11VideoRenderer::PaintOnMainThread)); } -void X11VideoRenderer::Paint() { +void X11VideoRenderer::PaintOnMainThread() { + DCHECK_EQ(main_message_loop_, MessageLoop::current()); + scoped_refptr<media::VideoFrame> video_frame; GetCurrentFrame(&video_frame); if (!image_ || !video_frame) { diff --git a/media/tools/player_x11/x11_video_renderer.h b/media/tools/player_x11/x11_video_renderer.h index 51e4996..d208779 100644 --- a/media/tools/player_x11/x11_video_renderer.h +++ b/media/tools/player_x11/x11_video_renderer.h @@ -8,24 +8,14 @@ #include <X11/Xlib.h> #include "base/memory/scoped_ptr.h" -#include "media/base/filters.h" #include "media/filters/video_renderer_base.h" class MessageLoop; class X11VideoRenderer : public media::VideoRendererBase { public: - X11VideoRenderer(Display* display, Window window, MessageLoop* message_loop); - - // This method is called to paint the current video frame to the assigned - // window. - void Paint(); - - static X11VideoRenderer* instance() { return instance_; } - - MessageLoop* glx_thread_message_loop() { - return glx_thread_message_loop_; - } + X11VideoRenderer(Display* display, Window window, + MessageLoop* main_message_loop); protected: // VideoRendererBase implementation. @@ -38,6 +28,8 @@ class X11VideoRenderer : public media::VideoRendererBase { friend class scoped_refptr<X11VideoRenderer>; virtual ~X11VideoRenderer(); + void PaintOnMainThread(); + Display* display_; Window window_; @@ -50,8 +42,7 @@ class X11VideoRenderer : public media::VideoRendererBase { bool use_render_; - MessageLoop* glx_thread_message_loop_; - static X11VideoRenderer* instance_; + MessageLoop* main_message_loop_; DISALLOW_COPY_AND_ASSIGN(X11VideoRenderer); }; |