1 /* $Id$ */
2 /*
3  * Copyright (C) 2010-2011 Teluu Inc. (http://www.teluu.com)
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19 #include <pjmedia/converter.h>
20 #include <pj/assert.h>
21 #include <pj/errno.h>
22 
23 #define THIS_FILE	"converter.c"
24 
25 struct pjmedia_converter_mgr
26 {
27     pjmedia_converter_factory  factory_list;
28 };
29 
30 static pjmedia_converter_mgr *converter_manager_instance;
31 
32 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) && \
33     defined(PJMEDIA_HAS_LIBSWSCALE) && (PJMEDIA_HAS_LIBSWSCALE != 0)
34 PJ_DECL(pj_status_t)
35 pjmedia_libswscale_converter_init(pjmedia_converter_mgr *mgr);
36 #endif
37 
38 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) && \
39     defined(PJMEDIA_HAS_LIBYUV) && (PJMEDIA_HAS_LIBYUV != 0)
40 PJ_DECL(pj_status_t)
41 pjmedia_libyuv_converter_init(pjmedia_converter_mgr *mgr);
42 #endif
43 
pjmedia_converter_mgr_create(pj_pool_t * pool,pjmedia_converter_mgr ** p_mgr)44 PJ_DEF(pj_status_t) pjmedia_converter_mgr_create(pj_pool_t *pool,
45 					         pjmedia_converter_mgr **p_mgr)
46 {
47     pjmedia_converter_mgr *mgr;
48     pj_status_t status = PJ_SUCCESS;
49 
50     mgr = PJ_POOL_ALLOC_T(pool, pjmedia_converter_mgr);
51     pj_list_init(&mgr->factory_list);
52 
53     if (!converter_manager_instance)
54 	converter_manager_instance = mgr;
55 
56 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) && \
57     defined(PJMEDIA_HAS_LIBSWSCALE) && (PJMEDIA_HAS_LIBSWSCALE != 0)
58     status = pjmedia_libswscale_converter_init(mgr);
59     if (status != PJ_SUCCESS) {
60 	PJ_PERROR(4,(THIS_FILE, status,
61 		     "Error initializing libswscale converter"));
62     }
63 #endif
64 
65 #if defined(PJMEDIA_HAS_VIDEO) && (PJMEDIA_HAS_VIDEO != 0) && \
66     defined(PJMEDIA_HAS_LIBYUV) && (PJMEDIA_HAS_LIBYUV != 0)
67     status = pjmedia_libyuv_converter_init(mgr);
68     if (status != PJ_SUCCESS) {
69 	PJ_PERROR(4,(THIS_FILE, status,
70 		     "Error initializing libyuv converter"));
71     }
72 #endif
73 
74     if (p_mgr)
75 	*p_mgr = mgr;
76 
77     return status;
78 }
79 
pjmedia_converter_mgr_instance(void)80 PJ_DEF(pjmedia_converter_mgr*) pjmedia_converter_mgr_instance(void)
81 {
82     pj_assert(converter_manager_instance != NULL);
83     return converter_manager_instance;
84 }
85 
pjmedia_converter_mgr_set_instance(pjmedia_converter_mgr * mgr)86 PJ_DEF(void) pjmedia_converter_mgr_set_instance(pjmedia_converter_mgr *mgr)
87 {
88     converter_manager_instance = mgr;
89 }
90 
pjmedia_converter_mgr_destroy(pjmedia_converter_mgr * mgr)91 PJ_DEF(void) pjmedia_converter_mgr_destroy(pjmedia_converter_mgr *mgr)
92 {
93     pjmedia_converter_factory *f;
94 
95     if (!mgr) mgr = pjmedia_converter_mgr_instance();
96 
97     PJ_ASSERT_ON_FAIL(mgr != NULL, return);
98 
99     f = mgr->factory_list.next;
100     while (f != &mgr->factory_list) {
101 	pjmedia_converter_factory *next = f->next;
102 	pj_list_erase(f);
103 	(*f->op->destroy_factory)(f);
104 	f = next;
105     }
106 
107     if (converter_manager_instance == mgr)
108 	converter_manager_instance = NULL;
109 }
110 
111 PJ_DEF(pj_status_t)
pjmedia_converter_mgr_register_factory(pjmedia_converter_mgr * mgr,pjmedia_converter_factory * factory)112 pjmedia_converter_mgr_register_factory(pjmedia_converter_mgr *mgr,
113 				       pjmedia_converter_factory *factory)
114 {
115     pjmedia_converter_factory *pf;
116 
117     if (!mgr) mgr = pjmedia_converter_mgr_instance();
118 
119     PJ_ASSERT_RETURN(mgr != NULL, PJ_EINVAL);
120 
121     PJ_ASSERT_RETURN(!pj_list_find_node(&mgr->factory_list, factory),
122 		     PJ_EEXISTS);
123 
124     pf = mgr->factory_list.next;
125     while (pf != &mgr->factory_list) {
126 	if (pf->priority > factory->priority)
127 	    break;
128 	pf = pf->next;
129     }
130     pj_list_insert_before(pf, factory);
131     return PJ_SUCCESS;
132 }
133 
134 
135 PJ_DEF(pj_status_t)
pjmedia_converter_mgr_unregister_factory(pjmedia_converter_mgr * mgr,pjmedia_converter_factory * f,pj_bool_t destroy)136 pjmedia_converter_mgr_unregister_factory(pjmedia_converter_mgr *mgr,
137 				         pjmedia_converter_factory *f,
138 				         pj_bool_t destroy)
139 {
140     if (!mgr) mgr = pjmedia_converter_mgr_instance();
141 
142     PJ_ASSERT_RETURN(mgr != NULL, PJ_EINVAL);
143 
144     PJ_ASSERT_RETURN(pj_list_find_node(&mgr->factory_list, f), PJ_ENOTFOUND);
145     pj_list_erase(f);
146     if (destroy)
147 	(*f->op->destroy_factory)(f);
148     return PJ_SUCCESS;
149 }
150 
pjmedia_converter_create(pjmedia_converter_mgr * mgr,pj_pool_t * pool,pjmedia_conversion_param * param,pjmedia_converter ** p_cv)151 PJ_DEF(pj_status_t) pjmedia_converter_create(pjmedia_converter_mgr *mgr,
152 					      pj_pool_t *pool,
153 					      pjmedia_conversion_param *param,
154 					      pjmedia_converter **p_cv)
155 {
156     pjmedia_converter_factory *f;
157     pjmedia_converter *cv = NULL;
158     pj_status_t status = PJ_ENOTFOUND;
159 
160     if (!mgr) mgr = pjmedia_converter_mgr_instance();
161 
162     PJ_ASSERT_RETURN(mgr != NULL, PJ_EINVAL);
163 
164     *p_cv = NULL;
165 
166     f = mgr->factory_list.next;
167     while (f != &mgr->factory_list) {
168 	status = (*f->op->create_converter)(f, pool, param, &cv);
169 	if (status == PJ_SUCCESS)
170 	    break;
171 	f = f->next;
172     }
173 
174     if (status != PJ_SUCCESS)
175 	return status;
176 
177     *p_cv = cv;
178 
179     return PJ_SUCCESS;
180 }
181 
pjmedia_converter_convert(pjmedia_converter * cv,pjmedia_frame * src_frame,pjmedia_frame * dst_frame)182 PJ_DEF(pj_status_t) pjmedia_converter_convert(pjmedia_converter *cv,
183 					       pjmedia_frame *src_frame,
184 					       pjmedia_frame *dst_frame)
185 {
186     return (*cv->op->convert)(cv, src_frame, dst_frame);
187 }
188 
pjmedia_converter_destroy(pjmedia_converter * cv)189 PJ_DEF(void) pjmedia_converter_destroy(pjmedia_converter *cv)
190 {
191     (*cv->op->destroy)(cv);
192 }
193 
pjmedia_converter_convert2(pjmedia_converter * cv,pjmedia_frame * src_frame,const pjmedia_rect_size * src_frame_size,const pjmedia_coord * src_pos,pjmedia_frame * dst_frame,const pjmedia_rect_size * dst_frame_size,const pjmedia_coord * dst_pos,void * param)194 PJ_DEF(pj_status_t) pjmedia_converter_convert2(
195 				    pjmedia_converter	    *cv,
196 				    pjmedia_frame	    *src_frame,
197 				    const pjmedia_rect_size *src_frame_size,
198 				    const pjmedia_coord	    *src_pos,
199 				    pjmedia_frame	    *dst_frame,
200 				    const pjmedia_rect_size *dst_frame_size,
201 				    const pjmedia_coord	    *dst_pos,
202 				    void		    *param)
203 {
204     if (!cv->op->convert2)
205 	return PJ_ENOTSUP;
206 
207     return (*cv->op->convert2)(cv, src_frame, src_frame_size, src_pos,
208 			       dst_frame, dst_frame_size, dst_pos, param);
209 }
210 
211