| 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 <X11/Xutil.h> | 8 #include <X11/Xutil.h> |
| 9 #include <X11/extensions/Xrender.h> | 9 #include <X11/extensions/Xrender.h> |
| 10 #include <X11/extensions/Xcomposite.h> | 10 #include <X11/extensions/Xcomposite.h> |
| 11 | 11 |
| 12 #include "media/base/buffers.h" | 12 #include "media/base/buffers.h" |
| 13 #include "media/base/pipeline.h" | 13 #include "media/base/pipeline.h" |
| 14 #include "media/base/filter_host.h" | 14 #include "media/base/filter_host.h" |
| 15 #include "media/base/video_frame.h" |
| 15 #include "media/base/yuv_convert.h" | 16 #include "media/base/yuv_convert.h" |
| 16 | 17 |
| 17 GlesVideoRenderer* GlesVideoRenderer::instance_ = NULL; | 18 GlesVideoRenderer* GlesVideoRenderer::instance_ = NULL; |
| 18 | 19 |
| 19 GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window) | 20 GlesVideoRenderer::GlesVideoRenderer(Display* display, Window window) |
| 20 : display_(display), | 21 : display_(display), |
| 21 window_(window), | 22 window_(window), |
| 22 new_frame_(false), | 23 new_frame_(false), |
| 23 egl_display_(NULL), | 24 egl_display_(NULL), |
| 24 egl_surface_(NULL), | 25 egl_surface_(NULL), |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 142 } | 143 } |
| 143 initialized = true; | 144 initialized = true; |
| 144 | 145 |
| 145 scoped_refptr<media::VideoFrame> video_frame; | 146 scoped_refptr<media::VideoFrame> video_frame; |
| 146 GetCurrentFrame(&video_frame); | 147 GetCurrentFrame(&video_frame); |
| 147 | 148 |
| 148 if (!video_frame) | 149 if (!video_frame) |
| 149 return; | 150 return; |
| 150 | 151 |
| 151 // Convert YUV frame to RGB. | 152 // Convert YUV frame to RGB. |
| 152 media::VideoSurface frame_in; | 153 DCHECK(video_frame->format() == media::VideoFrame::YV12 || |
| 153 if (video_frame->Lock(&frame_in)) { | 154 video_frame->format() == media::VideoFrame::YV16); |
| 154 DCHECK(frame_in.format == media::VideoSurface::YV12 || | 155 DCHECK(video_frame->stride(media::VideoFrame::kUPlane) == |
| 155 frame_in.format == media::VideoSurface::YV16); | 156 video_frame->stride(media::VideoFrame::kVPlane)); |
| 156 DCHECK(frame_in.strides[media::VideoSurface::kUPlane] == | 157 DCHECK(video_frame->planes() == media::VideoFrame::kNumYUVPlanes); |
| 157 frame_in.strides[media::VideoSurface::kVPlane]); | |
| 158 DCHECK(frame_in.planes == media::VideoSurface::kNumYUVPlanes); | |
| 159 | 158 |
| 160 for (unsigned int i = 0; i < media::VideoSurface::kNumYUVPlanes; ++i) { | 159 for (unsigned int i = 0; i < media::VideoFrame::kNumYUVPlanes; ++i) { |
| 161 unsigned int width = (i == media::VideoSurface::kYPlane) ? | 160 unsigned int width = (i == media::VideoFrame::kYPlane) ? |
| 162 frame_in.width : frame_in.width / 2; | 161 video_frame->width() : video_frame->width() / 2; |
| 163 unsigned int height = (i == media::VideoSurface::kYPlane || | 162 unsigned int height = (i == media::VideoFrame::kYPlane || |
| 164 frame_in.format == media::VideoSurface::YV16) ? | 163 video_frame->format() == media::VideoFrame::YV16) ? |
| 165 frame_in.height : frame_in.height / 2; | 164 video_frame->height() : video_frame->height() / 2; |
| 166 glActiveTexture(GL_TEXTURE0 + i); | 165 glActiveTexture(GL_TEXTURE0 + i); |
| 167 // GLES2 supports a fixed set of unpack alignments that should match most | 166 // GLES2 supports a fixed set of unpack alignments that should match most |
| 168 // of the time what ffmpeg outputs. | 167 // of the time what ffmpeg outputs. |
| 169 // TODO(piman): check if it is more efficient to prefer higher | 168 // TODO(piman): check if it is more efficient to prefer higher |
| 170 // alignments. | 169 // alignments. |
| 171 unsigned int stride = frame_in.strides[i]; | 170 unsigned int stride = video_frame->stride(i); |
| 172 uint8* data = frame_in.data[i]; | 171 uint8* data = video_frame->data(i); |
| 173 if (stride == width) { | 172 if (stride == width) { |
| 174 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); | 173 glPixelStorei(GL_UNPACK_ALIGNMENT, 1); |
| 175 } else if (stride == ((width + 1) & ~1)) { | 174 } else if (stride == ((width + 1) & ~1)) { |
| 176 glPixelStorei(GL_UNPACK_ALIGNMENT, 2); | 175 glPixelStorei(GL_UNPACK_ALIGNMENT, 2); |
| 177 } else if (stride == ((width + 3) & ~3)) { | 176 } else if (stride == ((width + 3) & ~3)) { |
| 178 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); | 177 glPixelStorei(GL_UNPACK_ALIGNMENT, 4); |
| 179 } else if (stride == ((width + 7) & ~7)) { | 178 } else if (stride == ((width + 7) & ~7)) { |
| 180 glPixelStorei(GL_UNPACK_ALIGNMENT, 8); | 179 glPixelStorei(GL_UNPACK_ALIGNMENT, 8); |
| 181 } else { | 180 } else { |
| 182 // Otherwise do it line-by-line. | 181 // Otherwise do it line-by-line. |
| 183 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, | 182 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, |
| 184 GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); | 183 GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL); |
| 185 for (unsigned int y = 0; y < height; ++y) { | 184 for (unsigned int y = 0; y < height; ++y) { |
| 186 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, width, 1, | 185 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, y, width, 1, |
| 187 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | 186 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| 188 data += stride; | 187 data += stride; |
| 189 } | |
| 190 continue; | |
| 191 } | 188 } |
| 192 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, | 189 continue; |
| 193 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); | |
| 194 } | 190 } |
| 195 video_frame->Unlock(); | 191 |
| 196 } else { | 192 glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, |
| 197 NOTREACHED(); | 193 GL_LUMINANCE, GL_UNSIGNED_BYTE, data); |
| 198 } | 194 } |
| 199 | 195 |
| 200 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); | 196 glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); |
| 201 eglSwapBuffers(egl_display_, egl_surface_); | 197 eglSwapBuffers(egl_display_, egl_surface_); |
| 202 } | 198 } |
| 203 | 199 |
| 204 bool GlesVideoRenderer::InitializeGles() { | 200 bool GlesVideoRenderer::InitializeGles() { |
| 205 // Resize the window to fit that of the video. | 201 // Resize the window to fit that of the video. |
| 206 XResizeWindow(display_, window_, width_, height_); | 202 XResizeWindow(display_, window_, width_, height_); |
| 207 | 203 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 282 } | 278 } |
| 283 | 279 |
| 284 EGLint width; | 280 EGLint width; |
| 285 EGLint height; | 281 EGLint height; |
| 286 eglQuerySurface(egl_display_, egl_surface_, EGL_WIDTH, &width); | 282 eglQuerySurface(egl_display_, egl_surface_, EGL_WIDTH, &width); |
| 287 eglQuerySurface(egl_display_, egl_surface_, EGL_HEIGHT, &height); | 283 eglQuerySurface(egl_display_, egl_surface_, EGL_HEIGHT, &height); |
| 288 glViewport(0, 0, width_, height_); | 284 glViewport(0, 0, width_, height_); |
| 289 | 285 |
| 290 // Create 3 textures, one for each plane, and bind them to different | 286 // Create 3 textures, one for each plane, and bind them to different |
| 291 // texture units. | 287 // texture units. |
| 292 glGenTextures(media::VideoSurface::kNumYUVPlanes, textures_); | 288 glGenTextures(media::VideoFrame::kNumYUVPlanes, textures_); |
| 293 | 289 |
| 294 glActiveTexture(GL_TEXTURE0); | 290 glActiveTexture(GL_TEXTURE0); |
| 295 glBindTexture(GL_TEXTURE_2D, textures_[0]); | 291 glBindTexture(GL_TEXTURE_2D, textures_[0]); |
| 296 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 292 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| 297 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); | 293 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); |
| 298 glEnable(GL_TEXTURE_2D); | 294 glEnable(GL_TEXTURE_2D); |
| 299 | 295 |
| 300 glActiveTexture(GL_TEXTURE1); | 296 glActiveTexture(GL_TEXTURE1); |
| 301 glBindTexture(GL_TEXTURE_2D, textures_[1]); | 297 glBindTexture(GL_TEXTURE_2D, textures_[1]); |
| 302 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); | 298 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 376 kTextureCoords); | 372 kTextureCoords); |
| 377 | 373 |
| 378 // We are getting called on a thread. Release the context so that it can be | 374 // We are getting called on a thread. Release the context so that it can be |
| 379 // made current on the main thread. | 375 // made current on the main thread. |
| 380 // TODO(hclam): Fix this if neccessary. Currently the following call fails | 376 // TODO(hclam): Fix this if neccessary. Currently the following call fails |
| 381 // for some drivers. | 377 // for some drivers. |
| 382 // eglMakeCurrent(egl_display_, EGL_NO_SURFACE, | 378 // eglMakeCurrent(egl_display_, EGL_NO_SURFACE, |
| 383 // EGL_NO_SURFACE, EGL_NO_CONTEXT); | 379 // EGL_NO_SURFACE, EGL_NO_CONTEXT); |
| 384 return true; | 380 return true; |
| 385 } | 381 } |
| OLD | NEW |