| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "media/tools/player_x11/gles_video_renderer.h" | 5 #include "media/tools/player_x11/gles_video_renderer.h" |
| 6 | 6 |
| 7 #include <dlfcn.h> | 7 #include <dlfcn.h> |
| 8 #include <EGL/eglext.h> | 8 #include <EGL/eglext.h> |
| 9 #include <X11/Xutil.h> | 9 #include <X11/Xutil.h> |
| 10 #include <X11/extensions/Xrender.h> | 10 #include <X11/extensions/Xrender.h> |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 const media::MediaFormat& media_format) { | 37 const media::MediaFormat& media_format) { |
| 38 int width = 0; | 38 int width = 0; |
| 39 int height = 0; | 39 int height = 0; |
| 40 bool uses_egl_image_ = false; | 40 bool uses_egl_image_ = false; |
| 41 return ParseMediaFormat(media_format, &width, &height, &uses_egl_image_); | 41 return ParseMediaFormat(media_format, &width, &height, &uses_egl_image_); |
| 42 } | 42 } |
| 43 | 43 |
| 44 void GlesVideoRenderer::OnStop() { | 44 void GlesVideoRenderer::OnStop() { |
| 45 // TODO(hclam): Context switching seems to be broek so the following | 45 // TODO(hclam): Context switching seems to be broek so the following |
| 46 // calls may fail. Need to fix them. | 46 // calls may fail. Need to fix them. |
| 47 eglMakeCurrent(egl_display_, EGL_NO_SURFACE, |
| 48 EGL_NO_SURFACE, EGL_NO_CONTEXT); |
| 47 for (size_t i = 0; i < egl_frames_.size(); ++i) { | 49 for (size_t i = 0; i < egl_frames_.size(); ++i) { |
| 48 scoped_refptr<media::VideoFrame> frame = egl_frames_[i].first; | 50 scoped_refptr<media::VideoFrame> frame = egl_frames_[i].first; |
| 49 if (frame->private_buffer()) | 51 if (frame->private_buffer()) |
| 50 egl_destroy_image_khr_(egl_display_, frame->private_buffer()); | 52 egl_destroy_image_khr_(egl_display_, frame->private_buffer()); |
| 51 if (egl_frames_[i].second) | 53 if (egl_frames_[i].second) |
| 52 glDeleteTextures(1, &egl_frames_[i].second); | 54 glDeleteTextures(1, &egl_frames_[i].second); |
| 53 } | 55 } |
| 54 egl_frames_.clear(); | 56 egl_frames_.clear(); |
| 55 eglMakeCurrent(egl_display_, EGL_NO_SURFACE, | |
| 56 EGL_NO_SURFACE, EGL_NO_CONTEXT); | |
| 57 eglDestroyContext(egl_display_, egl_context_); | 57 eglDestroyContext(egl_display_, egl_context_); |
| 58 eglDestroySurface(egl_display_, egl_surface_); | 58 eglDestroySurface(egl_display_, egl_surface_); |
| 59 } | 59 } |
| 60 | 60 |
| 61 // Matrix used for the YUV to RGB conversion. | 61 // Matrix used for the YUV to RGB conversion. |
| 62 static const float kYUV2RGB[9] = { | 62 static const float kYUV2RGB[9] = { |
| 63 1.f, 1.f, 1.f, | 63 1.f, 1.f, 1.f, |
| 64 0.f, -.344f, 1.772f, | 64 0.f, -.344f, 1.772f, |
| 65 1.403f, -.714f, 0.f, | 65 1.403f, -.714f, 0.f, |
| 66 }; | 66 }; |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 168 | 168 |
| 169 scoped_refptr<media::VideoFrame> video_frame; | 169 scoped_refptr<media::VideoFrame> video_frame; |
| 170 GetCurrentFrame(&video_frame); | 170 GetCurrentFrame(&video_frame); |
| 171 | 171 |
| 172 if (!video_frame.get()) { | 172 if (!video_frame.get()) { |
| 173 return; | 173 return; |
| 174 } | 174 } |
| 175 | 175 |
| 176 if (uses_egl_image_) { | 176 if (uses_egl_image_) { |
| 177 if (media::VideoFrame::TYPE_EGL_IMAGE == video_frame->type()) { | 177 if (media::VideoFrame::TYPE_EGL_IMAGE == video_frame->type()) { |
| 178 glActiveTexture(GL_TEXTURE0); | 178 |
| 179 EGLImageKHR egl_image = | 179 GLuint texture = FindTexture(video_frame); |
| 180 reinterpret_cast<EGLImageKHR>(video_frame->private_buffer()); | 180 if (texture) { |
| 181 gl_eglimage_target_texture2d_oes_(GL_TEXTURE_2D, egl_image); | 181 glActiveTexture(GL_TEXTURE0); |
| 182 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 182 glBindTexture(GL_TEXTURE_2D, texture); |
| 183 eglSwapBuffers(egl_display_, egl_surface_); | 183 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 184 eglSwapBuffers(egl_display_, egl_surface_); |
| 185 } |
| 184 } | 186 } |
| 185 return; | 187 return; |
| 186 } | 188 } |
| 187 | 189 |
| 188 // Convert YUV frame to RGB. | 190 // Convert YUV frame to RGB. |
| 189 DCHECK(video_frame->format() == media::VideoFrame::YV12 || | 191 DCHECK(video_frame->format() == media::VideoFrame::YV12 || |
| 190 video_frame->format() == media::VideoFrame::YV16); | 192 video_frame->format() == media::VideoFrame::YV16); |
| 191 DCHECK(video_frame->stride(media::VideoFrame::kUPlane) == | 193 DCHECK(video_frame->stride(media::VideoFrame::kUPlane) == |
| 192 video_frame->stride(media::VideoFrame::kVPlane)); | 194 video_frame->stride(media::VideoFrame::kVPlane)); |
| 193 DCHECK(video_frame->planes() == media::VideoFrame::kNumYUVPlanes); | 195 DCHECK(video_frame->planes() == media::VideoFrame::kNumYUVPlanes); |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 226 } | 228 } |
| 227 | 229 |
| 228 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, | 230 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, |
| 229 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | 231 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| 230 } | 232 } |
| 231 | 233 |
| 232 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 234 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 233 eglSwapBuffers(egl_display_, egl_surface_); | 235 eglSwapBuffers(egl_display_, egl_surface_); |
| 234 } | 236 } |
| 235 | 237 |
| 238 // find if texture exists corresponding to video_frame |
| 239 GLuint GlesVideoRenderer::FindTexture( |
| 240 scoped_refptr<media::VideoFrame> video_frame) { |
| 241 for (size_t i = 0; i < egl_frames_.size(); ++i) { |
| 242 scoped_refptr<media::VideoFrame> frame = egl_frames_[i].first; |
| 243 if (video_frame->private_buffer() == frame->private_buffer()) |
| 244 return egl_frames_[i].second; |
| 245 } |
| 246 return NULL; |
| 247 } |
| 248 |
| 236 bool GlesVideoRenderer::InitializeGles() { | 249 bool GlesVideoRenderer::InitializeGles() { |
| 237 // Resize the window to fit that of the video. | 250 // Resize the window to fit that of the video. |
| 238 XResizeWindow(display_, window_, width_, height_); | 251 XResizeWindow(display_, window_, width_, height_); |
| 239 | 252 |
| 240 egl_display_ = eglGetDisplay(display_); | 253 egl_display_ = eglGetDisplay(display_); |
| 241 if (eglGetError() != EGL_SUCCESS) { | 254 if (eglGetError() != EGL_SUCCESS) { |
| 242 DLOG(ERROR) << "eglGetDisplay failed."; | 255 DLOG(ERROR) << "eglGetDisplay failed."; |
| 243 return false; | 256 return false; |
| 244 } | 257 } |
| 245 | 258 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 366 int len; | 379 int len; |
| 367 glGetProgramInfoLog(program, kErrorSize - 1, &len, log); | 380 glGetProgramInfoLog(program, kErrorSize - 1, &len, log); |
| 368 log[kErrorSize - 1] = 0; | 381 log[kErrorSize - 1] = 0; |
| 369 LOG(FATAL) << log; | 382 LOG(FATAL) << log; |
| 370 } | 383 } |
| 371 glUseProgram(program); | 384 glUseProgram(program); |
| 372 glDeleteProgram(program); | 385 glDeleteProgram(program); |
| 373 } | 386 } |
| 374 | 387 |
| 375 void GlesVideoRenderer::CreateTextureAndProgramEgl() { | 388 void GlesVideoRenderer::CreateTextureAndProgramEgl() { |
| 376 if (!egl_create_image_khr_) { | 389 if (!egl_create_image_khr_) |
| 377 egl_create_image_khr_ = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC> | 390 egl_create_image_khr_ = reinterpret_cast<PFNEGLCREATEIMAGEKHRPROC> |
| 378 (eglGetProcAddress("eglCreateImageKHR")); | 391 (eglGetProcAddress("eglCreateImageKHR")); |
| 379 CHECK(egl_create_image_khr_); | 392 if (!egl_destroy_image_khr_) |
| 380 } | |
| 381 if (!egl_destroy_image_khr_) { | |
| 382 egl_destroy_image_khr_ = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC> | 393 egl_destroy_image_khr_ = reinterpret_cast<PFNEGLDESTROYIMAGEKHRPROC> |
| 383 (eglGetProcAddress("eglDestroyImageKHR")); | 394 (eglGetProcAddress("eglDestroyImageKHR")); |
| 384 CHECK(egl_destroy_image_khr_); | |
| 385 } | |
| 386 | |
| 387 if (!gl_eglimage_target_texture2d_oes_) { | |
| 388 gl_eglimage_target_texture2d_oes_ = | |
| 389 reinterpret_cast<PFNGLEGLIMAGETARGETTEXTURE2DOESPROC> | |
| 390 (eglGetProcAddress("glEGLImageTargetTexture2DOES")); | |
| 391 CHECK(gl_eglimage_target_texture2d_oes_); | |
| 392 } | |
| 393 | |
| 394 // TODO(wjia): get count from decoder. | 395 // TODO(wjia): get count from decoder. |
| 395 for (int i = 0; i < 4; i++) { | 396 for (int i = 0; i < 4; i++) { |
| 396 GLuint texture; | 397 GLuint texture; |
| 397 EGLint attrib = EGL_NONE; | 398 EGLint attrib = EGL_NONE; |
| 398 EGLImageKHR egl_image; | 399 EGLImageKHR egl_image; |
| 399 | 400 |
| 400 glGenTextures(1, &texture); | 401 glGenTextures(1, &texture); |
| 401 glBindTexture(GL_TEXTURE_2D, texture); | 402 glBindTexture(GL_TEXTURE_2D, texture); |
| 402 glTexImage2D( | 403 glTexImage2D( |
| 403 GL_TEXTURE_2D, | 404 GL_TEXTURE_2D, |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 496 | 497 |
| 497 int pos_location = glGetAttribLocation(program, "in_pos"); | 498 int pos_location = glGetAttribLocation(program, "in_pos"); |
| 498 glEnableVertexAttribArray(pos_location); | 499 glEnableVertexAttribArray(pos_location); |
| 499 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); | 500 glVertexAttribPointer(pos_location, 2, GL_FLOAT, GL_FALSE, 0, kVertices); |
| 500 | 501 |
| 501 int tc_location = glGetAttribLocation(program, "in_tc"); | 502 int tc_location = glGetAttribLocation(program, "in_tc"); |
| 502 glEnableVertexAttribArray(tc_location); | 503 glEnableVertexAttribArray(tc_location); |
| 503 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, | 504 glVertexAttribPointer(tc_location, 2, GL_FLOAT, GL_FALSE, 0, |
| 504 kTextureCoords); | 505 kTextureCoords); |
| 505 } | 506 } |
| OLD | NEW |