1 /******************************************************************************
2     Copyright (C) 2014 by Hugh Bailey <obs.jim@gmail.com>
3 
4     This program is free software: you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation, either version 2 of the License, or
7     (at your option) any later version.
8 
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13 
14     You should have received a copy of the GNU General Public License
15     along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 ******************************************************************************/
17 
18 #include "obs.h"
19 #include "obs-internal.h"
20 
obs_view_init(struct obs_view * view)21 bool obs_view_init(struct obs_view *view)
22 {
23 	if (!view)
24 		return false;
25 
26 	pthread_mutex_init_value(&view->channels_mutex);
27 
28 	if (pthread_mutex_init(&view->channels_mutex, NULL) != 0) {
29 		blog(LOG_ERROR, "obs_view_init: Failed to create mutex");
30 		return false;
31 	}
32 
33 	return true;
34 }
35 
obs_view_create(void)36 obs_view_t *obs_view_create(void)
37 {
38 	struct obs_view *view = bzalloc(sizeof(struct obs_view));
39 
40 	if (!obs_view_init(view)) {
41 		bfree(view);
42 		view = NULL;
43 	}
44 
45 	return view;
46 }
47 
obs_view_free(struct obs_view * view)48 void obs_view_free(struct obs_view *view)
49 {
50 	if (!view)
51 		return;
52 
53 	for (size_t i = 0; i < MAX_CHANNELS; i++) {
54 		struct obs_source *source = view->channels[i];
55 		if (source) {
56 			obs_source_deactivate(source, AUX_VIEW);
57 			obs_source_release(source);
58 		}
59 	}
60 
61 	memset(view->channels, 0, sizeof(view->channels));
62 	pthread_mutex_destroy(&view->channels_mutex);
63 }
64 
obs_view_destroy(obs_view_t * view)65 void obs_view_destroy(obs_view_t *view)
66 {
67 	if (view) {
68 		obs_view_free(view);
69 		bfree(view);
70 	}
71 }
72 
obs_view_get_source(obs_view_t * view,uint32_t channel)73 obs_source_t *obs_view_get_source(obs_view_t *view, uint32_t channel)
74 {
75 	obs_source_t *source;
76 	assert(channel < MAX_CHANNELS);
77 
78 	if (!view)
79 		return NULL;
80 	if (channel >= MAX_CHANNELS)
81 		return NULL;
82 
83 	pthread_mutex_lock(&view->channels_mutex);
84 
85 	source = view->channels[channel];
86 	if (source)
87 		obs_source_addref(source);
88 
89 	pthread_mutex_unlock(&view->channels_mutex);
90 
91 	return source;
92 }
93 
obs_view_set_source(obs_view_t * view,uint32_t channel,obs_source_t * source)94 void obs_view_set_source(obs_view_t *view, uint32_t channel,
95 			 obs_source_t *source)
96 {
97 	struct obs_source *prev_source;
98 
99 	assert(channel < MAX_CHANNELS);
100 
101 	if (!view)
102 		return;
103 	if (channel >= MAX_CHANNELS)
104 		return;
105 
106 	pthread_mutex_lock(&view->channels_mutex);
107 
108 	obs_source_addref(source);
109 
110 	prev_source = view->channels[channel];
111 	view->channels[channel] = source;
112 
113 	pthread_mutex_unlock(&view->channels_mutex);
114 
115 	if (source)
116 		obs_source_activate(source, AUX_VIEW);
117 
118 	if (prev_source) {
119 		obs_source_deactivate(prev_source, AUX_VIEW);
120 		obs_source_release(prev_source);
121 	}
122 }
123 
obs_view_render(obs_view_t * view)124 void obs_view_render(obs_view_t *view)
125 {
126 	if (!view)
127 		return;
128 
129 	pthread_mutex_lock(&view->channels_mutex);
130 
131 	for (size_t i = 0; i < MAX_CHANNELS; i++) {
132 		struct obs_source *source;
133 
134 		source = view->channels[i];
135 
136 		if (source) {
137 			if (source->removed) {
138 				obs_source_release(source);
139 				view->channels[i] = NULL;
140 			} else {
141 				obs_source_video_render(source);
142 			}
143 		}
144 	}
145 
146 	pthread_mutex_unlock(&view->channels_mutex);
147 }
148