1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 package org.opencastproject.inspection.ffmpeg;
23
24 import org.opencastproject.inspection.api.MediaInspectionException;
25 import org.opencastproject.inspection.api.MediaInspectionService;
26 import org.opencastproject.inspection.api.util.Options;
27 import org.opencastproject.job.api.AbstractJobProducer;
28 import org.opencastproject.job.api.Job;
29 import org.opencastproject.mediapackage.MediaPackageElement;
30 import org.opencastproject.mediapackage.MediaPackageElementParser;
31 import org.opencastproject.mediapackage.MediaPackageException;
32 import org.opencastproject.security.api.OrganizationDirectoryService;
33 import org.opencastproject.security.api.SecurityService;
34 import org.opencastproject.security.api.UserDirectoryService;
35 import org.opencastproject.serviceregistry.api.ServiceRegistry;
36 import org.opencastproject.serviceregistry.api.ServiceRegistryException;
37 import org.opencastproject.util.LoadUtil;
38 import org.opencastproject.workspace.api.Workspace;
39
40 import org.osgi.service.component.ComponentContext;
41 import org.osgi.service.component.annotations.Activate;
42 import org.osgi.service.component.annotations.Component;
43 import org.osgi.service.component.annotations.Modified;
44 import org.osgi.service.component.annotations.Reference;
45 import org.slf4j.Logger;
46 import org.slf4j.LoggerFactory;
47
48 import java.net.URI;
49 import java.util.Arrays;
50 import java.util.Dictionary;
51 import java.util.List;
52 import java.util.Map;
53
54
55 @Component(
56 property = {
57 "service.description=Media Inspection Service",
58 "service.pid=org.opencastproject.inspection.ffmpeg.MediaInspectionServiceImpl"
59 },
60 immediate = true,
61 service = { MediaInspectionService.class }
62 )
63 public class MediaInspectionServiceImpl extends AbstractJobProducer implements MediaInspectionService {
64
65
66 public static final float DEFAULT_INSPECT_JOB_LOAD = 0.2f;
67
68
69 public static final float DEFAULT_ENRICH_JOB_LOAD = 0.2f;
70
71
72 public static final String INSPECT_JOB_LOAD_KEY = "job.load.inspect";
73
74
75 public static final String ENRICH_JOB_LOAD_KEY = "job.load.enrich";
76
77
78 private float inspectJobLoad = DEFAULT_INSPECT_JOB_LOAD;
79
80
81 private float enrichJobLoad = DEFAULT_ENRICH_JOB_LOAD;
82
83 private static final Logger logger = LoggerFactory.getLogger(MediaInspectionServiceImpl.class);
84
85
86 private enum Operation {
87 Inspect, Enrich
88 }
89
90 private Workspace workspace;
91 private ServiceRegistry serviceRegistry;
92 private SecurityService securityService = null;
93 private UserDirectoryService userDirectoryService = null;
94 private OrganizationDirectoryService organizationDirectoryService = null;
95
96 private volatile MediaInspector inspector;
97
98
99 public MediaInspectionServiceImpl() {
100 super(JOB_TYPE);
101 }
102
103 @Override
104 @Activate
105 public void activate(ComponentContext cc) {
106 super.activate(cc);
107
108 final String path = cc.getBundleContext().getProperty(FFmpegAnalyzer.FFPROBE_BINARY_CONFIG);
109 final String ffprobeBinary;
110 if (path == null) {
111 logger.debug("DEFAULT " + FFmpegAnalyzer.FFPROBE_BINARY_CONFIG + ": " + FFmpegAnalyzer.FFPROBE_BINARY_DEFAULT);
112 ffprobeBinary = FFmpegAnalyzer.FFPROBE_BINARY_DEFAULT;
113 } else {
114 logger.debug("FFprobe config binary: {}", path);
115 ffprobeBinary = path;
116 }
117 inspector = new MediaInspector(workspace, ffprobeBinary);
118 }
119
120 @Modified
121 public void modified(ComponentContext cc) {
122 Dictionary<String, Object> properties = cc.getProperties();
123 if (properties == null) {
124 logger.info("No configuration available, using defaults");
125 return;
126 }
127 inspectJobLoad = LoadUtil.getConfiguredLoadValue(properties, INSPECT_JOB_LOAD_KEY, DEFAULT_INSPECT_JOB_LOAD,
128 serviceRegistry);
129 enrichJobLoad = LoadUtil.getConfiguredLoadValue(properties, ENRICH_JOB_LOAD_KEY, DEFAULT_ENRICH_JOB_LOAD,
130 serviceRegistry);
131 logger.info("Configuration updated");
132 }
133
134
135
136
137
138
139 @Override
140 protected String process(Job job) throws Exception {
141 Operation op = null;
142 String operation = job.getOperation();
143 List<String> arguments = job.getArguments();
144 try {
145 op = Operation.valueOf(operation);
146 MediaPackageElement inspectedElement = null;
147 Map<String, String> options = null;
148 switch (op) {
149 case Inspect:
150 URI uri = URI.create(arguments.get(0));
151 options = Options.fromJson(arguments.get(1));
152 inspectedElement = inspector.inspectTrack(uri, options);
153 break;
154 case Enrich:
155 MediaPackageElement element = MediaPackageElementParser.getFromXml(arguments.get(0));
156 boolean overwrite = Boolean.parseBoolean(arguments.get(1));
157 options = Options.fromJson(arguments.get(2));
158 inspectedElement = inspector.enrich(element, overwrite, options);
159 break;
160 default:
161 throw new IllegalStateException("Don't know how to handle operation '" + operation + "'");
162 }
163 return MediaPackageElementParser.getAsXml(inspectedElement);
164 } catch (IllegalArgumentException e) {
165 throw new ServiceRegistryException("This service can't handle operations of type '" + op + "'", e);
166 } catch (IndexOutOfBoundsException e) {
167 throw new ServiceRegistryException("This argument list for operation '" + op + "' does not meet expectations", e);
168 } catch (Exception e) {
169 throw new ServiceRegistryException("Error handling operation '" + op + "'", e);
170 }
171 }
172
173
174
175
176
177
178 @Override
179 public Job inspect(URI uri) throws MediaInspectionException {
180 return inspect(uri, Options.NO_OPTION);
181 }
182
183
184
185
186
187
188 @Override
189 public Job inspect(URI uri, final Map<String,String> options) throws MediaInspectionException {
190 assert (options != null);
191 try {
192 return serviceRegistry.createJob(JOB_TYPE, Operation.Inspect.toString(), Arrays.asList(uri.toString(),
193 Options.toJson(options)), inspectJobLoad);
194 } catch (ServiceRegistryException e) {
195 throw new MediaInspectionException(e);
196 }
197 }
198
199
200
201
202
203
204
205 @Override
206 public Job enrich(final MediaPackageElement element, final boolean override)
207 throws MediaInspectionException, MediaPackageException {
208 return enrich(element, override, Options.NO_OPTION);
209 }
210
211
212
213
214
215
216
217 @Override
218 public Job enrich(final MediaPackageElement element, final boolean override, final Map<String,String> options)
219 throws MediaInspectionException, MediaPackageException {
220 assert (options != null);
221 try {
222 return serviceRegistry.createJob(JOB_TYPE, Operation.Enrich.toString(),
223 Arrays.asList(MediaPackageElementParser.getAsXml(element), Boolean.toString(override),
224 Options.toJson(options)), enrichJobLoad);
225 } catch (ServiceRegistryException e) {
226 throw new MediaInspectionException(e);
227 }
228 }
229
230 @Reference
231 protected void setWorkspace(Workspace workspace) {
232 logger.debug("setting " + workspace);
233 this.workspace = workspace;
234 }
235
236 @Reference
237 protected void setServiceRegistry(ServiceRegistry jobManager) {
238 this.serviceRegistry = jobManager;
239 }
240
241
242
243
244
245
246 @Override
247 protected ServiceRegistry getServiceRegistry() {
248 return serviceRegistry;
249 }
250
251
252
253
254
255
256
257 @Reference
258 public void setSecurityService(SecurityService securityService) {
259 this.securityService = securityService;
260 }
261
262
263
264
265
266
267
268 @Reference
269 public void setUserDirectoryService(UserDirectoryService userDirectoryService) {
270 this.userDirectoryService = userDirectoryService;
271 }
272
273
274
275
276
277
278
279 @Reference
280 public void setOrganizationDirectoryService(OrganizationDirectoryService organizationDirectory) {
281 this.organizationDirectoryService = organizationDirectory;
282 }
283
284
285
286
287
288
289 @Override
290 protected SecurityService getSecurityService() {
291 return securityService;
292 }
293
294
295
296
297
298
299 @Override
300 protected UserDirectoryService getUserDirectoryService() {
301 return userDirectoryService;
302 }
303
304
305
306
307
308
309 @Override
310 protected OrganizationDirectoryService getOrganizationDirectoryService() {
311 return organizationDirectoryService;
312 }
313 }