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.
5 #include "media/cast/test/linux_output_window.h"
9 #include "base/logging.h"
10 #include "media/base/video_frame.h"
11 #include "third_party/libyuv/include/libyuv/convert.h"
12 #include "ui/gfx/geometry/size.h"
18 LinuxOutputWindow::LinuxOutputWindow(int x_pos
,
22 const std::string
& name
) {
23 CreateWindow(x_pos
, y_pos
, width
, height
, name
);
26 LinuxOutputWindow::~LinuxOutputWindow() {
27 if (display_
&& window_
) {
28 XUnmapWindow(display_
, window_
);
29 XDestroyWindow(display_
, window_
);
30 XSync(display_
, false);
32 XFreeGC(display_
, gc_
);
33 XCloseDisplay(display_
);
37 void LinuxOutputWindow::CreateWindow(int x_pos
,
41 const std::string
& name
) {
42 display_
= XOpenDisplay(NULL
);
43 if (display_
== NULL
) {
44 // There's no point to continue if this happens: nothing will work anyway.
45 VLOG(1) << "Failed to connect to X server: X environment likely broken";
49 int screen
= DefaultScreen(display_
);
51 // Try to establish a 24-bit TrueColor display.
52 // (our environment must allow this).
53 XVisualInfo visual_info
;
54 if (XMatchVisualInfo(display_
, screen
, 24, TrueColor
, &visual_info
) == 0) {
55 VLOG(1) << "Failed to establish 24-bit TrueColor in X environment.";
59 // Create suitable window attributes.
60 XSetWindowAttributes window_attributes
;
61 window_attributes
.colormap
= XCreateColormap(
62 display_
, DefaultRootWindow(display_
), visual_info
.visual
, AllocNone
);
63 window_attributes
.event_mask
= StructureNotifyMask
| ExposureMask
;
64 window_attributes
.background_pixel
= 0;
65 window_attributes
.border_pixel
= 0;
67 unsigned long attribute_mask
=
68 CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
70 window_
= XCreateWindow(display_
,
71 DefaultRootWindow(display_
),
84 XStoreName(display_
, window_
, name
.c_str());
85 XSetIconName(display_
, window_
, name
.c_str());
87 // Make x report events for mask.
88 XSelectInput(display_
, window_
, StructureNotifyMask
);
90 // Map the window to the display.
91 XMapWindow(display_
, window_
);
93 // Wait for map event.
96 XNextEvent(display_
, &event
);
97 } while (event
.type
!= MapNotify
|| event
.xmap
.event
!= window_
);
99 gc_
= XCreateGC(display_
, window_
, 0, 0);
101 // create shared memory image
102 image_
= XShmCreateImage(
103 display_
, CopyFromParent
, 24, ZPixmap
, NULL
, &shminfo_
, width
, height
);
104 shminfo_
.shmid
= shmget(
105 IPC_PRIVATE
, (image_
->bytes_per_line
* image_
->height
), IPC_CREAT
| 0777);
106 shminfo_
.shmaddr
= image_
->data
= (char*)shmat(shminfo_
.shmid
, 0, 0);
107 if (image_
->data
== reinterpret_cast<char*>(-1)) {
108 VLOG(1) << "XShmCreateImage failed";
111 shminfo_
.readOnly
= false;
113 // Attach image to display.
114 if (!XShmAttach(display_
, &shminfo_
)) {
115 VLOG(1) << "XShmAttach failed";
118 XSync(display_
, false);
121 void LinuxOutputWindow::RenderFrame(
122 const scoped_refptr
<media::VideoFrame
>& video_frame
) {
123 const gfx::Size
damage_size(std::min(video_frame
->visible_rect().width(),
125 std::min(video_frame
->visible_rect().height(),
128 if (damage_size
.width() < image_
->width
||
129 damage_size
.height() < image_
->height
)
130 memset(image_
->data
, 0x00, image_
->bytes_per_line
* image_
->height
);
132 if (!damage_size
.IsEmpty()) {
133 libyuv::I420ToARGB(video_frame
->visible_data(VideoFrame::kYPlane
),
134 video_frame
->stride(VideoFrame::kYPlane
),
135 video_frame
->visible_data(VideoFrame::kUPlane
),
136 video_frame
->stride(VideoFrame::kUPlane
),
137 video_frame
->visible_data(VideoFrame::kVPlane
),
138 video_frame
->stride(VideoFrame::kVPlane
),
139 reinterpret_cast<uint8_t*>(image_
->data
),
140 image_
->bytes_per_line
,
142 damage_size
.height());
145 // Place image in window.
146 XShmPutImage(display_
,
158 // Very important for the image to update properly!
159 XSync(display_
, false);