1 | /* |
2 | Copyright (c) 2012, Broadcom Europe Ltd |
3 | All rights reserved. |
4 | |
5 | Redistribution and use in source and binary forms, with or without |
6 | modification, are permitted provided that the following conditions are met: |
7 | * Redistributions of source code must retain the above copyright |
8 | notice, this list of conditions and the following disclaimer. |
9 | * Redistributions in binary form must reproduce the above copyright |
10 | notice, this list of conditions and the following disclaimer in the |
11 | documentation and/or other materials provided with the distribution. |
12 | * Neither the name of the copyright holder nor the |
13 | names of its contributors may be used to endorse or promote products |
14 | derived from this software without specific prior written permission. |
15 | |
16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
17 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
18 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
19 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY |
20 | DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
21 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
22 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
23 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
24 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
25 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ |
27 | |
28 | #include <ctype.h> |
29 | #include <stdlib.h> |
30 | #include <string.h> |
31 | #include <stdio.h> |
32 | |
33 | #include "containers/containers.h" |
34 | #include "containers/core/containers_private.h" |
35 | #include "containers/core/containers_filters.h" |
36 | |
37 | #if !defined(ENABLE_CONTAINERS_STANDALONE) |
38 | #include "vcos_dlfcn.h" |
39 | #define DL_SUFFIX VCOS_SO_EXT |
40 | #ifndef DL_PATH_PREFIX |
41 | #define DL_PATH_PREFIX "" |
42 | #endif |
43 | #endif |
44 | |
45 | typedef struct VC_CONTAINER_FILTER_PRIVATE_T |
46 | { |
47 | /** Pointer to the container filter code and symbols */ |
48 | void *handle; |
49 | } VC_CONTAINER_FILTER_PRIVATE_T; |
50 | |
51 | typedef VC_CONTAINER_STATUS_T (*VC_CONTAINER_FILTER_OPEN_FUNC_T)(VC_CONTAINER_FILTER_T*, VC_CONTAINER_FOURCC_T); |
52 | |
53 | static VC_CONTAINER_FILTER_OPEN_FUNC_T load_library(void **handle, VC_CONTAINER_FOURCC_T filter, const char *name); |
54 | static void unload_library(void *handle); |
55 | |
56 | static struct { |
57 | VC_CONTAINER_FOURCC_T filter; |
58 | const char *name; |
59 | } filter_to_name_table[] = |
60 | { |
61 | {VC_FOURCC('d','r','m',' '), "divx" }, |
62 | {VC_FOURCC('d','r','m',' '), "hdcp2" }, |
63 | {0, NULL} |
64 | }; |
65 | |
66 | static VC_CONTAINER_STATUS_T vc_container_filter_load(VC_CONTAINER_FILTER_T *p_ctx, |
67 | VC_CONTAINER_FOURCC_T filter, |
68 | VC_CONTAINER_FOURCC_T type) |
69 | { |
70 | void *handle = NULL; |
71 | VC_CONTAINER_FILTER_OPEN_FUNC_T func; |
72 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED; |
73 | unsigned int i; |
74 | |
75 | for(i = 0; filter_to_name_table[i].filter; ++i) |
76 | { |
77 | if (filter_to_name_table[i].filter == filter) |
78 | { |
79 | if ((func = load_library(&handle, filter, filter_to_name_table[i].name)) != NULL) |
80 | { |
81 | status = (*func)(p_ctx, type); |
82 | if(status == VC_CONTAINER_SUCCESS) break; |
83 | unload_library(handle); |
84 | if (status != VC_CONTAINER_ERROR_FORMAT_NOT_SUPPORTED) break; |
85 | } |
86 | } |
87 | } |
88 | |
89 | p_ctx->priv->handle = handle; |
90 | return status; |
91 | } |
92 | |
93 | static void vc_container_filter_unload(VC_CONTAINER_FILTER_T *p_ctx) |
94 | { |
95 | unload_library(p_ctx->priv->handle); |
96 | p_ctx->priv->handle = NULL; |
97 | } |
98 | |
99 | /*****************************************************************************/ |
100 | VC_CONTAINER_FILTER_T *vc_container_filter_open(VC_CONTAINER_FOURCC_T filter, |
101 | VC_CONTAINER_FOURCC_T type, |
102 | VC_CONTAINER_T *p_container, |
103 | VC_CONTAINER_STATUS_T *p_status ) |
104 | { |
105 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_NOT_FOUND; |
106 | VC_CONTAINER_FILTER_T *p_ctx = 0; |
107 | VC_CONTAINER_FILTER_PRIVATE_T *priv = 0; |
108 | |
109 | /* Allocate our context before trying out the different filter modules */ |
110 | p_ctx = malloc(sizeof(*p_ctx) + sizeof(*priv)); |
111 | if(!p_ctx) { status = VC_CONTAINER_ERROR_OUT_OF_MEMORY; goto error; } |
112 | memset(p_ctx, 0, sizeof(*p_ctx) + sizeof(*priv)); |
113 | p_ctx->priv = priv = (VC_CONTAINER_FILTER_PRIVATE_T *)&p_ctx[1]; |
114 | p_ctx->container = p_container; |
115 | |
116 | status = vc_container_filter_load(p_ctx, filter, type); |
117 | if(status != VC_CONTAINER_SUCCESS) goto error; |
118 | |
119 | end: |
120 | if(p_status) *p_status = status; |
121 | return p_ctx; |
122 | |
123 | error: |
124 | if(p_ctx) free(p_ctx); |
125 | p_ctx = 0; |
126 | goto end; |
127 | } |
128 | |
129 | /*****************************************************************************/ |
130 | VC_CONTAINER_STATUS_T vc_container_filter_close( VC_CONTAINER_FILTER_T *p_ctx ) |
131 | { |
132 | if (p_ctx) |
133 | { |
134 | if(p_ctx->pf_close) p_ctx->pf_close(p_ctx); |
135 | if(p_ctx->priv && p_ctx->priv->handle) vc_container_filter_unload(p_ctx); |
136 | free(p_ctx); |
137 | } |
138 | return VC_CONTAINER_SUCCESS; |
139 | } |
140 | |
141 | /*****************************************************************************/ |
142 | VC_CONTAINER_STATUS_T vc_container_filter_process( VC_CONTAINER_FILTER_T *p_ctx, VC_CONTAINER_PACKET_T *p_packet ) |
143 | { |
144 | VC_CONTAINER_STATUS_T status; |
145 | status = p_ctx->pf_process(p_ctx, p_packet); |
146 | return status; |
147 | } |
148 | |
149 | VC_CONTAINER_STATUS_T vc_container_filter_control(VC_CONTAINER_FILTER_T *p_ctx, VC_CONTAINER_CONTROL_T operation, ... ) |
150 | { |
151 | VC_CONTAINER_STATUS_T status = VC_CONTAINER_ERROR_UNSUPPORTED_OPERATION; |
152 | va_list args; |
153 | |
154 | va_start( args, operation ); |
155 | if(p_ctx->pf_control) |
156 | status = p_ctx->pf_control(p_ctx, operation, args); |
157 | va_end( args ); |
158 | |
159 | return status; |
160 | } |
161 | |
162 | static VC_CONTAINER_FILTER_OPEN_FUNC_T load_library(void **handle, VC_CONTAINER_FOURCC_T filter, const char *name) |
163 | { |
164 | VC_CONTAINER_FILTER_OPEN_FUNC_T func = NULL; |
165 | #ifdef ENABLE_CONTAINERS_STANDALONE |
166 | VC_CONTAINER_PARAM_UNUSED(handle); |
167 | VC_CONTAINER_PARAM_UNUSED(filter); |
168 | VC_CONTAINER_PARAM_UNUSED(name); |
169 | #else |
170 | char *dl_name, *entrypt_name; |
171 | const char *entrypt_name_short = "filter_open" ; |
172 | char filter_[6], *ptr; |
173 | void *dl_handle; |
174 | int dl_name_len; |
175 | int entrypt_name_len; |
176 | |
177 | snprintf(filter_, sizeof(filter_), "%4.4s" , (const char*)&filter); |
178 | ptr = strchr(filter_, '\0'); |
179 | while (ptr > filter_ && isspace(*--ptr)) *ptr = '\0'; |
180 | strncat(filter_, "_" , 1); |
181 | |
182 | dl_name_len = strlen(DL_PATH_PREFIX) + strlen(filter_) + strlen(name) + strlen(DL_SUFFIX) + 1; |
183 | dl_name = malloc(dl_name_len); |
184 | if (!dl_name) return NULL; |
185 | |
186 | entrypt_name_len = strlen(name) + 1 + strlen(filter_) + strlen(entrypt_name_short) + 1; |
187 | entrypt_name = malloc(entrypt_name_len); |
188 | if (!entrypt_name) |
189 | { |
190 | free(dl_name); |
191 | return NULL; |
192 | } |
193 | |
194 | snprintf(dl_name, dl_name_len, "%s%s%s%s" , DL_PATH_PREFIX, filter_, name, DL_SUFFIX); |
195 | snprintf(entrypt_name, entrypt_name_len, "%s_%s%s" , name, filter_, entrypt_name_short); |
196 | |
197 | if ((dl_handle = vcos_dlopen(dl_name, VCOS_DL_NOW)) != NULL) |
198 | { |
199 | /* Try generic entrypoint name before the mangled, full name */ |
200 | func = (VC_CONTAINER_FILTER_OPEN_FUNC_T)vcos_dlsym(dl_handle, entrypt_name_short); |
201 | if (!func) func = (VC_CONTAINER_FILTER_OPEN_FUNC_T)vcos_dlsym(dl_handle, entrypt_name); |
202 | /* Only return handle if symbol found */ |
203 | if (func) |
204 | *handle = dl_handle; |
205 | else |
206 | vcos_dlclose(dl_handle); |
207 | } |
208 | |
209 | free(dl_name); |
210 | free(entrypt_name); |
211 | #endif |
212 | return func; |
213 | } |
214 | |
215 | static void unload_library(void *handle) |
216 | { |
217 | #ifdef ENABLE_CONTAINERS_STANDALONE |
218 | VC_CONTAINER_PARAM_UNUSED(handle); |
219 | #else |
220 | vcos_dlclose(handle); |
221 | #endif |
222 | } |
223 | |