Home | History | Annotate | Download | only in test
      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