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 = 66 CWBackPixel | CWBorderPixel | CWColormap | CWEventMask; 67 68 window_ = XCreateWindow(display_, 69 DefaultRootWindow(display_), 70 x_pos, 71 y_pos, 72 width, 73 height, 74 0, 75 visual_info.depth, 76 InputOutput, 77 visual_info.visual, 78 attribute_mask, 79 &window_attributes); 80 81 // Set window name. 82 XStoreName(display_, window_, name.c_str()); 83 XSetIconName(display_, window_, name.c_str()); 84 85 // Make x report events for mask. 86 XSelectInput(display_, window_, StructureNotifyMask); 87 88 // Map the window to the display. 89 XMapWindow(display_, window_); 90 91 // Wait for map event. 92 XEvent event; 93 do { 94 XNextEvent(display_, &event); 95 } while (event.type != MapNotify || event.xmap.event != window_); 96 97 gc_ = XCreateGC(display_, window_, 0, 0); 98 99 // create shared memory image 100 image_ = XShmCreateImage( 101 display_, CopyFromParent, 24, ZPixmap, NULL, &shminfo_, width, height); 102 shminfo_.shmid = shmget( 103 IPC_PRIVATE, (image_->bytes_per_line * image_->height), IPC_CREAT | 0777); 104 shminfo_.shmaddr = image_->data = (char*)shmat(shminfo_.shmid, 0, 0); 105 if (image_->data == reinterpret_cast<char*>(-1)) { 106 VLOG(1) << "XShmCreateImage failed"; 107 NOTREACHED(); 108 } 109 shminfo_.readOnly = false; 110 111 // Attach image to display. 112 if (!XShmAttach(display_, &shminfo_)) { 113 VLOG(1) << "XShmAttach failed"; 114 NOTREACHED(); 115 } 116 XSync(display_, false); 117 } 118 119 void LinuxOutputWindow::RenderFrame( 120 const scoped_refptr<media::VideoFrame>& video_frame) { 121 CHECK_LE(video_frame->coded_size().width(), image_->width); 122 CHECK_LE(video_frame->coded_size().height(), image_->height); 123 libyuv::I420ToARGB(video_frame->data(VideoFrame::kYPlane), 124 video_frame->stride(VideoFrame::kYPlane), 125 video_frame->data(VideoFrame::kUPlane), 126 video_frame->stride(VideoFrame::kUPlane), 127 video_frame->data(VideoFrame::kVPlane), 128 video_frame->stride(VideoFrame::kVPlane), 129 reinterpret_cast<uint8_t*>(image_->data), 130 image_->bytes_per_line, 131 video_frame->coded_size().width(), 132 video_frame->coded_size().height()); 133 134 // Place image in window. 135 XShmPutImage(display_, 136 window_, 137 gc_, 138 image_, 139 0, 140 0, 141 0, 142 0, 143 video_frame->coded_size().width(), 144 video_frame->coded_size().height(), 145 true); 146 147 // Very important for the image to update properly! 148 XSync(display_, false); 149 } 150 151 } // namespace test 152 } // namespace cast 153 } // namespace media 154