summaryrefslogtreecommitdiffstats
path: root/media/tools
diff options
context:
space:
mode:
authorwjia@google.com <wjia@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-07 20:05:42 +0000
committerwjia@google.com <wjia@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2010-06-07 20:05:42 +0000
commit84a661708faa4431cdba5833a33c7834389c65ef (patch)
tree4143eefac3569a4523c4af4984ebddb95400274c /media/tools
parent62dae71cec04b8d040ef86e1bfb4516d13080a97 (diff)
downloadchromium_src-84a661708faa4431cdba5833a33c7834389c65ef.zip
chromium_src-84a661708faa4431cdba5833a33c7834389c65ef.tar.gz
chromium_src-84a661708faa4431cdba5833a33c7834389c65ef.tar.bz2
add support of OpenMAX EGL image decoding
add support of GLES2 EGL image rendering OpenMAX system memory decoding almost works expect flow control in video renderer base BUG=none TEST=dev platform Review URL: http://codereview.chromium.org/2456006 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@49089 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media/tools')
-rw-r--r--media/tools/omx_test/omx_test.cc2
-rw-r--r--media/tools/player_x11/gles_video_renderer.cc239
-rw-r--r--media/tools/player_x11/gles_video_renderer.h15
3 files changed, 199 insertions, 57 deletions
diff --git a/media/tools/omx_test/omx_test.cc b/media/tools/omx_test/omx_test.cc
index 560e6d6..2deddeb 100644
--- a/media/tools/omx_test/omx_test.cc
+++ b/media/tools/omx_test/omx_test.cc
@@ -127,7 +127,7 @@ class TestApp : public base::RefCountedThreadSafe<TestApp> {
first_sample_delivered_time_ = base::TimeTicks::HighResNow();
// If we are readding to the end, then stop.
- if (frame.get() == NULL) {
+ if (frame->IsEndOfStream()) {
engine_->Stop(NewCallback(this, &TestApp::StopCallback));
return;
}
diff --git a/media/tools/player_x11/gles_video_renderer.cc b/media/tools/player_x11/gles_video_renderer.cc
index 85e4329..a275366 100644
--- a/media/tools/player_x11/gles_video_renderer.cc
+++ b/media/tools/player_x11/gles_video_renderer.cc
@@ -5,6 +5,7 @@
#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>
@@ -18,7 +19,9 @@
GlesVideoRenderer* GlesVideoRenderer::instance_ = NULL;
GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window)
- : display_(display),
+ : egl_create_image_khr_(NULL),
+ egl_destroy_image_khr_(NULL),
+ display_(display),
window_(window),
new_frame_(false),
egl_display_(NULL),
@@ -43,6 +46,14 @@ void GlesVideoRenderer::OnStop() {
// calls may fail. Need to fix them.
eglMakeCurrent(egl_display_, EGL_NO_SURFACE,
EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ 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();
eglDestroyContext(egl_display_, egl_context_);
eglDestroySurface(egl_display_, egl_surface_);
}
@@ -70,6 +81,14 @@ static const float kTextureCoords[8] = {
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"
@@ -103,6 +122,16 @@ static const char kFragmentShader[] =
" gl_FragColor = vec4(rgb, 1);\n"
"}\n";
+// Color shader for EGLImage.
+static const char kFragmentShaderEgl[] =
+ "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;
@@ -149,8 +178,23 @@ void GlesVideoRenderer::Paint() {
scoped_refptr<media::VideoFrame> video_frame;
GetCurrentFrame(&video_frame);
- if (!video_frame)
+ if (!video_frame.get()) {
return;
+ }
+
+ if (uses_egl_image_) {
+ if (media::VideoFrame::TYPE_EGL_IMAGE == 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_);
+ }
+ }
+ return;
+ }
// Convert YUV frame to RGB.
DCHECK(video_frame->format() == media::VideoFrame::YV12 ||
@@ -200,6 +244,17 @@ void GlesVideoRenderer::Paint() {
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_);
@@ -288,6 +343,127 @@ bool GlesVideoRenderer::InitializeGles() {
eglQuerySurface(egl_display_, egl_surface_, EGL_HEIGHT, &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;
+ 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;
+ 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;
+ media::VideoFrame:: CreatePrivateFrame(
+ media::VideoFrame::TYPE_EGL_IMAGE,
+ media::VideoFrame::RGB565,
+ width_, height_, kZero, kZero,
+ egl_image,
+ &video_frame);
+ egl_frames_.push_back(std::make_pair(video_frame, texture));
+ GetDecoder()->FillThisBuffer(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_);
@@ -313,52 +489,11 @@ bool GlesVideoRenderer::InitializeGles() {
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);
- glDeleteShader(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);
- glDeleteShader(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);
- glDeleteProgram(program);
+ CreateShader(program, GL_VERTEX_SHADER,
+ kVertexShader, sizeof(kVertexShader));
+ CreateShader(program, GL_FRAGMENT_SHADER,
+ kFragmentShaderEgl, sizeof(kFragmentShader));
+ LinkProgram(program);
// Bind parameters.
glUniform1i(glGetUniformLocation(program, "y_tex"), 0);
@@ -377,12 +512,4 @@ bool GlesVideoRenderer::InitializeGles() {
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.
- // 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;
}
diff --git a/media/tools/player_x11/gles_video_renderer.h b/media/tools/player_x11/gles_video_renderer.h
index 39478ac..075bdbc 100644
--- a/media/tools/player_x11/gles_video_renderer.h
+++ b/media/tools/player_x11/gles_video_renderer.h
@@ -6,12 +6,14 @@
#define MEDIA_TOOLS_PLAYER_X11_GL_VIDEO_RENDERER_H_
#include <EGL/egl.h>
+#include <EGL/eglext.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/base/video_frame.h"
#include "media/filters/video_renderer_base.h"
class GlesVideoRenderer : public media::VideoRendererBase {
@@ -44,7 +46,16 @@ class GlesVideoRenderer : public media::VideoRendererBase {
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();
+
+ PFNEGLCREATEIMAGEKHRPROC egl_create_image_khr_;
+ PFNEGLDESTROYIMAGEKHRPROC egl_destroy_image_khr_;
int width_;
int height_;
@@ -62,6 +73,10 @@ class GlesVideoRenderer : public media::VideoRendererBase {
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];