blob: a926879be3bfdb755a45bdef86f20007a2274f91 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001// libjingle
2// Copyright 2004 Google Inc.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6//
7// 1. Redistributions of source code must retain the above copyright notice,
8// this list of conditions and the following disclaimer.
9// 2. Redistributions in binary form must reproduce the above copyright notice,
10// this list of conditions and the following disclaimer in the documentation
11// and/or other materials provided with the distribution.
12// 3. The name of the author may not be used to endorse or promote products
13// derived from this software without specific prior written permission.
14//
15// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
16// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
19// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
21// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
24// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26// Implementation of GtkVideoRenderer
27
28#include "talk/media/devices/gtkvideorenderer.h"
29
30#include <glib.h>
31#include <gdk/gdk.h>
32#include <gtk/gtk.h>
33
34#include "talk/media/base/videocommon.h"
35#include "talk/media/base/videoframe.h"
36
37namespace cricket {
38
39class ScopedGdkLock {
40 public:
41 ScopedGdkLock() {
42 gdk_threads_enter();
43 }
44
45 ~ScopedGdkLock() {
46 gdk_threads_leave();
47 }
48};
49
50GtkVideoRenderer::GtkVideoRenderer(int x, int y)
51 : window_(NULL),
52 draw_area_(NULL),
53 initial_x_(x),
54 initial_y_(y) {
55 g_type_init();
56 g_thread_init(NULL);
57 gdk_threads_init();
58}
59
60GtkVideoRenderer::~GtkVideoRenderer() {
61 if (window_) {
62 ScopedGdkLock lock;
63 gtk_widget_destroy(window_);
64 // Run the Gtk main loop to tear down the window.
65 Pump();
66 }
67 // Don't need to destroy draw_area_ because it is not top-level, so it is
68 // implicitly destroyed by the above.
69}
70
71bool GtkVideoRenderer::SetSize(int width, int height, int reserved) {
72 ScopedGdkLock lock;
73
74 // For the first frame, initialize the GTK window
75 if ((!window_ && !Initialize(width, height)) || IsClosed()) {
76 return false;
77 }
78
79 image_.reset(new uint8[width * height * 4]);
80 gtk_widget_set_size_request(draw_area_, width, height);
81 return true;
82}
83
84bool GtkVideoRenderer::RenderFrame(const VideoFrame* frame) {
85 if (!frame) {
86 return false;
87 }
88
89 // convert I420 frame to ABGR format, which is accepted by GTK
90 frame->ConvertToRgbBuffer(cricket::FOURCC_ABGR,
91 image_.get(),
92 frame->GetWidth() * frame->GetHeight() * 4,
93 frame->GetWidth() * 4);
94
95 ScopedGdkLock lock;
96
97 if (IsClosed()) {
98 return false;
99 }
100
101 // draw the ABGR image
102 gdk_draw_rgb_32_image(draw_area_->window,
103 draw_area_->style->fg_gc[GTK_STATE_NORMAL],
104 0,
105 0,
106 frame->GetWidth(),
107 frame->GetHeight(),
108 GDK_RGB_DITHER_MAX,
109 image_.get(),
110 frame->GetWidth() * 4);
111
112 // Run the Gtk main loop to refresh the window.
113 Pump();
114 return true;
115}
116
117bool GtkVideoRenderer::Initialize(int width, int height) {
118 gtk_init(NULL, NULL);
119 window_ = gtk_window_new(GTK_WINDOW_TOPLEVEL);
120 draw_area_ = gtk_drawing_area_new();
121 if (!window_ || !draw_area_) {
122 return false;
123 }
124
125 gtk_window_set_position(GTK_WINDOW(window_), GTK_WIN_POS_CENTER);
126 gtk_window_set_title(GTK_WINDOW(window_), "Video Renderer");
127 gtk_window_set_resizable(GTK_WINDOW(window_), FALSE);
128 gtk_widget_set_size_request(draw_area_, width, height);
129 gtk_container_add(GTK_CONTAINER(window_), draw_area_);
130 gtk_widget_show_all(window_);
131 gtk_window_move(GTK_WINDOW(window_), initial_x_, initial_y_);
132
133 image_.reset(new uint8[width * height * 4]);
134 return true;
135}
136
137void GtkVideoRenderer::Pump() {
138 while (gtk_events_pending()) {
139 gtk_main_iteration();
140 }
141}
142
143bool GtkVideoRenderer::IsClosed() const {
144 if (!window_) {
145 // Not initialized yet, so hasn't been closed.
146 return false;
147 }
148
149 if (!GTK_IS_WINDOW(window_) || !GTK_IS_DRAWING_AREA(draw_area_)) {
150 return true;
151 }
152
153 return false;
154}
155
156} // namespace cricket