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"
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"
16 LinuxOutputWindow::LinuxOutputWindow(int x_pos
,
20 const std::string
& name
) {
21 CreateWindow(x_pos
, y_pos
, width
, height
, name
);
24 LinuxOutputWindow::~LinuxOutputWindow() {
25 if (display_
&& window_
) {
26 XUnmapWindow(display_
, window_
);
27 XDestroyWindow(display_
, window_
);
28 XSync(display_
, false);
30 XFreeGC(display_
, gc_
);
31 XCloseDisplay(display_
);
35 void LinuxOutputWindow::CreateWindow(int x_pos
,
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";
47 int screen
= DefaultScreen(display_
);
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.";
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;
65 unsigned long attribute_mask
=
66 CWBackPixel
| CWBorderPixel
| CWColormap
| CWEventMask
;
68 window_
= XCreateWindow(display_
,
69 DefaultRootWindow(display_
),
82 XStoreName(display_
, window_
, name
.c_str());
83 XSetIconName(display_
, window_
, name
.c_str());
85 // Make x report events for mask.
86 XSelectInput(display_
, window_
, StructureNotifyMask
);
88 // Map the window to the display.
89 XMapWindow(display_
, window_
);
91 // Wait for map event.
94 XNextEvent(display_
, &event
);
95 } while (event
.type
!= MapNotify
|| event
.xmap
.event
!= window_
);
97 gc_
= XCreateGC(display_
, window_
, 0, 0);
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";
109 shminfo_
.readOnly
= false;
111 // Attach image to display.
112 if (!XShmAttach(display_
, &shminfo_
)) {
113 VLOG(1) << "XShmAttach failed";
116 XSync(display_
, false);
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());
134 // Place image in window.
135 XShmPutImage(display_
,
143 video_frame
->coded_size().width(),
144 video_frame
->coded_size().height(),
147 // Very important for the image to update properly!
148 XSync(display_
, false);