1 // Copyright 2013 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "media/cast/test/linux_output_window.h" 6 7 #include "base/logging.h" 8 #include "media/base/video_frame.h" 9 #include "third_party/libyuv/include/libyuv/convert.h" 10 #include "ui/gfx/size.h" 11 12 namespace media { 13 namespace cast { 14 namespace test { 15 16 LinuxOutputWindow::LinuxOutputWindow(int x_pos, 17 int y_pos, 18 int width, 19 int height, 20 const std::string& name) { 21 CreateWindow( x_pos, y_pos, width, height, name); 22 } 23 24 LinuxOutputWindow::~LinuxOutputWindow() { 25 if (display_ && window_) { 26 XUnmapWindow(display_, window_); 27 XDestroyWindow(display_, window_); 28 XSync(display_, false); 29 if (gc_) 30 XFreeGC(display_, gc_); 31 XCloseDisplay(display_); 32 } 33 } 34 35 void LinuxOutputWindow::CreateWindow(int x_pos, 36 int y_pos, 37 int width, 38 int height, 39 const std::string& name) { 40 display_ = XOpenDisplay(NULL); 41 if (display_ == NULL) { 42 // There's no point to continue if this happens: nothing will work anyway. 43 VLOG(1) << "Failed to connect to X server: X environment likely broken"; 44 NOTREACHED(); 45 } 46 47 int screen = DefaultScreen(display_); 48 49 // Try to establish a 24-bit TrueColor display. 50 // (our environment must allow this). 51 XVisualInfo visual_info; 52 if (XMatchVisualInfo(display_, screen, 24, TrueColor, &visual_info) == 0) { 53 VLOG(1) << "Failed to establish 24-bit TrueColor in X environment."; 54 NOTREACHED(); 55 } 56 57 // Create suitable window attributes. 58 XSetWindowAttributes window_attributes; 59 window_attributes.colormap = XCreateColormap( 60 display_, DefaultRootWindow(display_), visual_info.visual, AllocNone); 61 window_attributes.event_mask = StructureNotifyMask | ExposureMask; 62 window_attributes.background_pixel = 0; 63 window_attributes.border_pixel = 0; 64 65 unsigned long attribute_mask = CWBackPixel | CWBorderPixel | CWColormap | 66 CWEventMask; 67 68 window_ = XCreateWindow(display_, DefaultRootWindow(display_), x_pos, 69 y_pos, width, height, 0, visual_info.depth, 70 InputOutput, visual_info.visual, 71 attribute_mask, &window_attributes); 72 73 // Set window name. 74 XStoreName(display_, window_, name.c_str()); 75 XSetIconName(display_, window_, name.c_str()); 76 77 // Make x report events for mask. 78 XSelectInput(display_, window_, StructureNotifyMask); 79 80 // Map the window to the display. 81 XMapWindow(display_, window_); 82 83 // Wait for map event. 84 XEvent event; 85 do { 86 XNextEvent(display_, &event); 87 } while (event.type != MapNotify || event.xmap.event != window_); 88 89 gc_ = XCreateGC(display_, window_, 0, 0); 90 91 // create shared memory image 92 image_ = XShmCreateImage(display_, CopyFromParent, 24, ZPixmap, NULL, 93 &shminfo_, width, height); 94 shminfo_.shmid = shmget(IPC_PRIVATE, 95 (image_->bytes_per_line * image_->height), 96 IPC_CREAT | 0777); 97 shminfo_.shmaddr = image_->data = (char*) shmat(shminfo_.shmid, 0, 0); 98 if (image_->data == reinterpret_cast<char*>(-1)) { 99 VLOG(1) << "XShmCreateImage failed"; 100 NOTREACHED(); 101 } 102 render_buffer_ = reinterpret_cast<uint8_t*>(image_->data); 103 shminfo_.readOnly = false; 104 105 // Attach image to display. 106 if (!XShmAttach(display_, &shminfo_)) { 107 VLOG(1) << "XShmAttach failed"; 108 NOTREACHED(); 109 } 110 XSync(display_, false); 111 } 112 113 void LinuxOutputWindow::RenderFrame( 114 const scoped_refptr<media::VideoFrame>& video_frame) { 115 libyuv::I420ToARGB(video_frame->data(VideoFrame::kYPlane), 116 video_frame->stride(VideoFrame::kYPlane), 117 video_frame->data(VideoFrame::kUPlane), 118 video_frame->stride(VideoFrame::kUPlane), 119 video_frame->data(VideoFrame::kVPlane), 120 video_frame->stride(VideoFrame::kVPlane), 121 render_buffer_, 122 video_frame->coded_size().width() * 4, // Stride. 123 video_frame->coded_size().width(), 124 video_frame->coded_size().height()); 125 126 // Place image in window. 127 XShmPutImage(display_, window_, gc_, image_, 0, 0, 0, 0, 128 video_frame->coded_size().width(), 129 video_frame->coded_size().height(), true); 130 131 // Very important for the image to update properly! 132 XSync(display_, false); 133 } 134 135 } // namespace test 136 } // namespace cast 137 } // namespace media