• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
LinuxOutputWindow(int x_pos,int y_pos,int width,int height,const std::string & name)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 
~LinuxOutputWindow()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 
CreateWindow(int x_pos,int y_pos,int width,int height,const std::string & name)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 
RenderFrame(const scoped_refptr<media::VideoFrame> & video_frame)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