summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-19 19:13:12 +0000
committerscherkus@chromium.org <scherkus@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-19 19:13:12 +0000
commita7fee967599ebc2bf996aba2c42b9257a5c29e68 (patch)
tree15dab1de10b5b2542d23e283864260d0ea400d2a /media
parentba412b9f51c8367c6a7baa2ace212ddeb1159137 (diff)
downloadchromium_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.gyp42
-rw-r--r--media/tools/player_x11/gl_video_renderer.cc23
-rw-r--r--media/tools/player_x11/gl_video_renderer.h21
-rw-r--r--media/tools/player_x11/gles_video_renderer.cc524
-rw-r--r--media/tools/player_x11/gles_video_renderer.h81
-rw-r--r--media/tools/player_x11/player_x11.cc59
-rw-r--r--media/tools/player_x11/x11_video_renderer.cc26
-rw-r--r--media/tools/player_x11/x11_video_renderer.h19
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);
};