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.composer.remote;
23
24 import org.opencastproject.composer.api.ComposerService;
25 import org.opencastproject.composer.api.EncoderException;
26 import org.opencastproject.composer.api.EncodingProfile;
27 import org.opencastproject.composer.api.EncodingProfileBuilder;
28 import org.opencastproject.composer.api.EncodingProfileImpl;
29 import org.opencastproject.composer.api.EncodingProfileList;
30 import org.opencastproject.composer.api.LaidOutElement;
31 import org.opencastproject.composer.layout.Dimension;
32 import org.opencastproject.composer.layout.Serializer;
33 import org.opencastproject.job.api.Job;
34 import org.opencastproject.job.api.JobParser;
35 import org.opencastproject.mediapackage.Attachment;
36 import org.opencastproject.mediapackage.MediaPackageElementParser;
37 import org.opencastproject.mediapackage.MediaPackageException;
38 import org.opencastproject.mediapackage.Track;
39 import org.opencastproject.security.api.TrustedHttpClient;
40 import org.opencastproject.serviceregistry.api.RemoteBase;
41 import org.opencastproject.serviceregistry.api.ServiceRegistry;
42 import org.opencastproject.smil.entity.api.Smil;
43 import org.opencastproject.util.data.Option;
44
45 import org.apache.commons.io.IOUtils;
46 import org.apache.commons.lang3.StringUtils;
47 import org.apache.http.HttpResponse;
48 import org.apache.http.HttpStatus;
49 import org.apache.http.client.entity.UrlEncodedFormEntity;
50 import org.apache.http.client.methods.HttpGet;
51 import org.apache.http.client.methods.HttpPost;
52 import org.apache.http.message.BasicNameValuePair;
53 import org.apache.http.util.EntityUtils;
54 import org.osgi.service.component.annotations.Component;
55 import org.osgi.service.component.annotations.Reference;
56 import org.slf4j.Logger;
57 import org.slf4j.LoggerFactory;
58
59 import java.io.IOException;
60 import java.nio.charset.Charset;
61 import java.util.ArrayList;
62 import java.util.Arrays;
63 import java.util.List;
64 import java.util.Locale;
65 import java.util.Map;
66 import java.util.Map.Entry;
67 import java.util.stream.Collectors;
68
69
70
71
72 @Component(
73 property = {
74 "service.description=Composer (Encoder) Remote Service Proxy"
75 },
76 immediate = true,
77 service = { ComposerService.class }
78 )
79 public class ComposerServiceRemoteImpl extends RemoteBase implements ComposerService {
80
81
82 private static final Logger logger = LoggerFactory.getLogger(ComposerServiceRemoteImpl.class);
83
84 public ComposerServiceRemoteImpl() {
85 super(JOB_TYPE);
86 }
87
88
89
90
91
92
93 @Override
94 @Reference
95 public void setTrustedHttpClient(TrustedHttpClient client) {
96 this.client = client;
97 }
98
99
100
101
102
103
104 @Override
105 @Reference
106 public void setRemoteServiceManager(ServiceRegistry remoteServiceManager) {
107 this.remoteServiceManager = remoteServiceManager;
108 }
109
110
111
112
113
114
115
116 @Override
117 public Job encode(Track sourceTrack, String profileId) throws EncoderException {
118 HttpPost post = new HttpPost("/encode");
119 try {
120 List<BasicNameValuePair> params = new ArrayList<>();
121 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
122 params.add(new BasicNameValuePair("profileId", profileId));
123 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
124 } catch (Exception e) {
125 throw new EncoderException("Unable to assemble a remote composer request for track " + sourceTrack, e);
126 }
127 HttpResponse response = null;
128 try {
129 response = getResponse(post);
130 if (response != null) {
131 String content = EntityUtils.toString(response.getEntity());
132 Job r = JobParser.parseJob(content);
133 logger.info("Encoding job {} started on a remote composer", r.getId());
134 return r;
135 }
136 } catch (Exception e) {
137 throw new EncoderException("Unable to encode track " + sourceTrack + " using a remote composer service", e);
138 } finally {
139 closeConnection(response);
140 }
141 throw new EncoderException("Unable to encode track " + sourceTrack + " using a remote composer service");
142 }
143
144
145
146
147 @Override
148 public Job parallelEncode(Track sourceTrack, String profileId) throws EncoderException {
149 HttpPost post = new HttpPost("/parallelencode");
150 try {
151 List<BasicNameValuePair> params = new ArrayList<>();
152 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
153 params.add(new BasicNameValuePair("profileId", profileId));
154 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
155 } catch (Exception e) {
156 throw new EncoderException("Unable to assemble a remote composer request for track " + sourceTrack, e);
157 }
158 HttpResponse response = null;
159 try {
160 response = getResponse(post);
161 if (response != null) {
162 String content = EntityUtils.toString(response.getEntity());
163 Job r = JobParser.parseJob(content);
164 logger.info("Encoding job {} started on a remote composer", r.getId());
165 return r;
166 }
167 } catch (Exception e) {
168 throw new EncoderException("Unable to encode track " + sourceTrack + " using a remote composer service", e);
169 } finally {
170 closeConnection(response);
171 }
172 throw new EncoderException("Unable to encode track " + sourceTrack + " using a remote composer service");
173 }
174
175
176
177
178
179
180 @Override
181 public Job trim(Track sourceTrack, String profileId, long start, long duration) throws EncoderException {
182 HttpPost post = new HttpPost("/trim");
183 try {
184 List<BasicNameValuePair> params = new ArrayList<>();
185 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
186 params.add(new BasicNameValuePair("profileId", profileId));
187 params.add(new BasicNameValuePair("start", Long.toString(start)));
188 params.add(new BasicNameValuePair("duration", Long.toString(duration)));
189 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
190 } catch (Exception e) {
191 throw new EncoderException("Unable to assemble a remote composer request for track " + sourceTrack, e);
192 }
193 HttpResponse response = null;
194 try {
195 response = getResponse(post);
196 if (response != null) {
197 String content = EntityUtils.toString(response.getEntity());
198 Job r = JobParser.parseJob(content);
199 logger.info("Trimming job {} started on a remote composer", r.getId());
200 return r;
201 }
202 } catch (Exception e) {
203 throw new EncoderException("Unable to trim track " + sourceTrack + " using a remote composer service", e);
204 } finally {
205 closeConnection(response);
206 }
207 throw new EncoderException("Unable to trim track " + sourceTrack + " using a remote composer service");
208 }
209
210
211
212
213
214
215
216 @Override
217 public Job mux(Track sourceVideoTrack, Track sourceAudioTrack, String profileId) throws EncoderException {
218 HttpPost post = new HttpPost("/mux");
219 try {
220 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
221 params.add(new BasicNameValuePair("videoSourceTrack", MediaPackageElementParser.getAsXml(sourceVideoTrack)));
222 params.add(new BasicNameValuePair("audioSourceTrack", MediaPackageElementParser.getAsXml(sourceAudioTrack)));
223 params.add(new BasicNameValuePair("profileId", profileId));
224 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
225 } catch (Exception e) {
226 throw new EncoderException("Unable to assemble a remote composer request", e);
227 }
228 HttpResponse response = null;
229 try {
230 response = getResponse(post);
231 if (response != null) {
232 String content = EntityUtils.toString(response.getEntity());
233 Job r = JobParser.parseJob(content);
234 logger.info("Muxing job {} started on a remote composer", r.getId());
235 return r;
236 }
237 } catch (IOException e) {
238 throw new EncoderException(e);
239 } finally {
240 closeConnection(response);
241 }
242 throw new EncoderException("Unable to mux tracks " + sourceVideoTrack + " and " + sourceAudioTrack
243 + " using a remote composer");
244 }
245
246
247
248
249
250
251 @Override
252 public Job mux(Map<String, Track> sourceTracks, String profileId) throws EncoderException {
253 HttpPost post = new HttpPost("/mux");
254 try {
255 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
256 List<String> sourceTracksEntries = new ArrayList<>();
257 for (Entry<String, Track> sourceTrack : sourceTracks.entrySet()) {
258 String sourceTrackXml = MediaPackageElementParser.getAsXml(sourceTrack.getValue());
259 sourceTracksEntries.add(StringUtils.join(sourceTrack.getKey(), "#=#", sourceTrackXml));
260 }
261 params.add(new BasicNameValuePair("sourceTracks", StringUtils.join(sourceTracksEntries, "#|#")));
262 params.add(new BasicNameValuePair("profileId", profileId));
263 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
264 } catch (Exception e) {
265 throw new EncoderException("Unable to assemble a remote composer request", e);
266 }
267 HttpResponse response = null;
268 try {
269 response = getResponse(post);
270 if (response != null) {
271 String content = EntityUtils.toString(response.getEntity());
272 Job r = JobParser.parseJob(content);
273 logger.info("Muxing job {} started on a remote composer", r.getId());
274 return r;
275 }
276 } catch (IOException e) {
277 throw new EncoderException(e);
278 } finally {
279 closeConnection(response);
280 }
281 throw new EncoderException("Unable to mux tracks " + sourceTracks.entrySet().stream()
282 .map(entry -> String.format("%s: %s", entry.getKey(), entry.getValue().getIdentifier())).collect(
283 Collectors.joining(", ")) + " using a remote composer");
284 }
285
286
287
288
289
290
291 @Override
292 public EncodingProfile getProfile(String profileId) {
293 HttpGet get = new HttpGet("/profile/" + profileId + ".xml");
294 HttpResponse response = null;
295 try {
296 response = getResponse(get, HttpStatus.SC_OK, HttpStatus.SC_NOT_FOUND);
297 if (response != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
298 return EncodingProfileBuilder.getInstance().parseProfile(response.getEntity().getContent());
299 } else {
300 return null;
301 }
302 } catch (Exception e) {
303 throw new RuntimeException(e);
304 } finally {
305 closeConnection(response);
306 }
307 }
308
309
310
311
312 @Override
313 public Job image(Track sourceTrack, String profileId, double... times) throws EncoderException {
314 HttpPost post = new HttpPost("/image");
315 try {
316 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
317 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
318 params.add(new BasicNameValuePair("profileId", profileId));
319 params.add(new BasicNameValuePair("time", buildTimeArray(times)));
320 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
321 } catch (Exception e) {
322 throw new EncoderException(e);
323 }
324 HttpResponse response = null;
325 try {
326 response = getResponse(post);
327 if (response != null) {
328 Job r = JobParser.parseJob(response.getEntity().getContent());
329 logger.info("Image extraction job {} started on a remote composer", r.getId());
330 return r;
331 }
332 } catch (Exception e) {
333 throw new EncoderException(e);
334 } finally {
335 closeConnection(response);
336 }
337 throw new EncoderException("Unable to compose an image from track " + sourceTrack
338 + " using the remote composer service proxy");
339 }
340
341 @Override
342 public List<Attachment> imageSync(Track sourceTrack, String profileId, double... times) throws EncoderException, MediaPackageException {
343 HttpPost post = new HttpPost("/imagesync");
344 try {
345 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
346 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
347 params.add(new BasicNameValuePair("profileId", profileId));
348 params.add(new BasicNameValuePair("time", buildTimeArray(times)));
349 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
350 } catch (Exception e) {
351 throw new EncoderException(e);
352 }
353 HttpResponse response = null;
354 try {
355 response = getResponse(post);
356 if (response != null) {
357 final String xml = IOUtils.toString(response.getEntity().getContent(), Charset.forName("utf-8"));
358 return MediaPackageElementParser.getArrayFromXml(xml)
359 .stream().map(e -> (Attachment)e)
360 .collect(Collectors.toList());
361 }
362 } catch (Exception e) {
363 throw new EncoderException(e);
364 } finally {
365 closeConnection(response);
366 }
367 throw new EncoderException("Unable to compose an image from track " + sourceTrack
368 + " using the remote composer service proxy");
369 }
370
371
372
373
374
375
376 @Override
377 public Job image(Track sourceTrack, String profileId, Map<String, String> properties) throws EncoderException,
378 MediaPackageException {
379 HttpPost post = new HttpPost("/image");
380 try {
381 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
382 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
383 params.add(new BasicNameValuePair("profileId", profileId));
384 if (properties != null)
385 params.add(new BasicNameValuePair("properties", mapToString(properties)));
386 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
387 } catch (Exception e) {
388 throw new EncoderException(e);
389 }
390 HttpResponse response = null;
391 try {
392 response = getResponse(post);
393 if (response != null) {
394 Job r = JobParser.parseJob(response.getEntity().getContent());
395 logger.info("Image extraction job {} started on a remote composer", r.getId());
396 return r;
397 }
398 } catch (Exception e) {
399 throw new EncoderException(e);
400 } finally {
401 closeConnection(response);
402 }
403 throw new EncoderException("Unable to compose an image from track " + sourceTrack
404 + " using the remote composer service proxy");
405 }
406
407
408
409
410
411
412
413 @Override
414 public Job convertImage(Attachment image, String... profileIds) throws EncoderException, MediaPackageException {
415 HttpPost post = new HttpPost("/convertimage");
416 try {
417 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
418 params.add(new BasicNameValuePair("sourceImage", MediaPackageElementParser.getAsXml(image)));
419 params.add(new BasicNameValuePair("profileId", StringUtils.join(profileIds, ',')));
420 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
421 } catch (Exception e) {
422 throw new EncoderException(e);
423 }
424 HttpResponse response = null;
425 try {
426 response = getResponse(post);
427 if (response != null) {
428 Job r = JobParser.parseJob(response.getEntity().getContent());
429 logger.info("Image conversion job {} started on a remote composer", r.getId());
430 return r;
431 }
432 } catch (Exception e) {
433 throw new EncoderException(e);
434 } finally {
435 closeConnection(response);
436 }
437 throw new EncoderException("Unable to convert image at " + image + " using the remote composer service proxy");
438 }
439
440
441
442
443
444
445
446 @Override
447 public List<Attachment> convertImageSync(Attachment image, String... profileIds) throws EncoderException, MediaPackageException {
448 HttpPost post = new HttpPost("/convertimagesync");
449 try {
450 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
451 params.add(new BasicNameValuePair("sourceImage", MediaPackageElementParser.getAsXml(image)));
452 params.add(new BasicNameValuePair("profileIds", StringUtils.join(profileIds, ',')));
453 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
454 } catch (Exception e) {
455 throw new EncoderException(e);
456 }
457 HttpResponse response = null;
458 try {
459 response = getResponse(post);
460 if (response != null) {
461 final String xml = IOUtils.toString(response.getEntity().getContent(), Charset.forName("utf-8"));
462 return MediaPackageElementParser.getArrayFromXml(xml).stream().map(a -> (Attachment) a).collect(Collectors.toList());
463 }
464 } catch (Exception e) {
465 throw new EncoderException(e);
466 } finally {
467 closeConnection(response);
468 }
469 throw new EncoderException("Unable to convert image at " + image + " using the remote composer service proxy");
470 }
471
472
473
474
475
476
477 @Override
478 public EncodingProfile[] listProfiles() {
479 HttpGet get = new HttpGet("/profiles.xml");
480 HttpResponse response = null;
481 try {
482 response = getResponse(get);
483 if (response != null) {
484 EncodingProfileList profileList = EncodingProfileBuilder.getInstance().parseProfileList(
485 response.getEntity().getContent());
486 List<EncodingProfileImpl> list = profileList.getProfiles();
487 return list.toArray(new EncodingProfile[list.size()]);
488 }
489 } catch (Exception e) {
490 throw new RuntimeException(
491 "Unable to list the encoding profiles registered with the remote composer service proxy", e);
492 } finally {
493 closeConnection(response);
494 }
495 throw new RuntimeException("Unable to list the encoding profiles registered with the remote composer service proxy");
496 }
497
498
499
500
501
502
503
504
505 protected String buildTimeArray(double[] times) {
506 if (times.length == 0)
507 return "";
508
509 StringBuilder builder = new StringBuilder();
510 builder.append(Double.toString(times[0]));
511 for (int i = 1; i < times.length; i++) {
512 builder.append(";" + Double.toString(times[i]));
513 }
514 return builder.toString();
515 }
516
517 @Override
518 public Job composite(Dimension compositeTrackSize, Option<LaidOutElement<Track>> upperTrack,
519 LaidOutElement<Track> lowerTrack, Option<LaidOutElement<Attachment>> watermark, String profileId,
520 String background, String sourceAudioName) throws EncoderException, MediaPackageException {
521 HttpPost post = new HttpPost("/composite");
522 try {
523 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
524 params.add(new BasicNameValuePair("compositeSize", Serializer.json(compositeTrackSize).toJson()));
525 params.add(new BasicNameValuePair("lowerTrack", MediaPackageElementParser.getAsXml(lowerTrack.getElement())));
526 params.add(new BasicNameValuePair("lowerLayout", Serializer.json(lowerTrack.getLayout()).toJson()));
527 if (upperTrack.isSome()) {
528 params.add(new BasicNameValuePair("upperTrack", MediaPackageElementParser.getAsXml(upperTrack.get()
529 .getElement())));
530 params.add(new BasicNameValuePair("upperLayout", Serializer.json(upperTrack.get().getLayout()).toJson()));
531 }
532
533 if (watermark.isSome()) {
534 params.add(new BasicNameValuePair("watermarkAttachment", MediaPackageElementParser.getAsXml(watermark.get()
535 .getElement())));
536 params.add(new BasicNameValuePair("watermarkLayout", Serializer.json(watermark.get().getLayout()).toJson()));
537 }
538 params.add(new BasicNameValuePair("profileId", profileId));
539 params.add(new BasicNameValuePair("background", background));
540 params.add(new BasicNameValuePair("sourceAudioName", sourceAudioName));
541 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
542 } catch (Exception e) {
543 throw new EncoderException(e);
544 }
545 HttpResponse response = null;
546 try {
547 response = getResponse(post);
548 if (response != null) {
549 Job r = JobParser.parseJob(response.getEntity().getContent());
550 logger.info("Composite video job {} started on a remote composer", r.getId());
551 return r;
552 }
553 } catch (Exception e) {
554 throw new EncoderException(e);
555 } finally {
556 closeConnection(response);
557 }
558 if (upperTrack.isSome()) {
559 throw new EncoderException("Unable to composite video from track " + lowerTrack.getElement() + " and "
560 + upperTrack.get().getElement() + " using the remote composer service proxy");
561 } else {
562 throw new EncoderException("Unable to composite video from track " + lowerTrack.getElement()
563 + " using the remote composer service proxy");
564 }
565 }
566
567 @Override
568 public Job concat(String profileId, Dimension outputDimension, boolean sameCodec, Track... tracks)
569 throws EncoderException, MediaPackageException {
570 return concat(profileId, outputDimension, -1.0f, sameCodec, tracks);
571 }
572
573 @Override
574 public Job concat(String profileId, Dimension outputDimension, float outputFrameRate, boolean sameCodec,
575 Track... tracks)
576 throws EncoderException, MediaPackageException {
577 HttpPost post = new HttpPost("/concat");
578 try {
579 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
580 params.add(new BasicNameValuePair("profileId", profileId));
581 if (outputDimension != null)
582 params.add(new BasicNameValuePair("outputDimension", Serializer.json(outputDimension).toJson()));
583 params.add(new BasicNameValuePair("outputFrameRate", String.format(Locale.US, "%f", outputFrameRate)));
584 params.add(new BasicNameValuePair("sourceTracks", MediaPackageElementParser.getArrayAsXml(Arrays.asList(tracks))));
585 if (sameCodec)
586 params.add(new BasicNameValuePair("sameCodec", "true"));
587 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
588 } catch (Exception e) {
589 throw new EncoderException(e);
590 }
591 HttpResponse response = null;
592 try {
593 response = getResponse(post);
594 if (response != null) {
595 Job r = JobParser.parseJob(response.getEntity().getContent());
596 logger.info("Concat video job {} started on a remote composer", r.getId());
597 return r;
598 }
599 } catch (Exception e) {
600 throw new EncoderException(e);
601 } finally {
602 closeConnection(response);
603 }
604 throw new EncoderException("Unable to concat videos from tracks " + tracks
605 + " using the remote composer service proxy");
606 }
607
608 @Override
609 public Job imageToVideo(Attachment sourceImageAttachment, String profileId, double time) throws EncoderException,
610 MediaPackageException {
611 HttpPost post = new HttpPost("/imagetovideo");
612 try {
613 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
614 params.add(new BasicNameValuePair("sourceAttachment", MediaPackageElementParser.getAsXml(sourceImageAttachment)));
615 params.add(new BasicNameValuePair("profileId", profileId));
616 params.add(new BasicNameValuePair("time", Double.toString(time)));
617 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
618 } catch (Exception e) {
619 throw new EncoderException(e);
620 }
621 HttpResponse response = null;
622 try {
623 response = getResponse(post);
624 if (response != null) {
625 Job r = JobParser.parseJob(response.getEntity().getContent());
626 logger.info("Image to video converting job {} started on a remote composer", r.getId());
627 return r;
628 }
629 } catch (Exception e) {
630 throw new EncoderException(e);
631 } finally {
632 closeConnection(response);
633 }
634 throw new EncoderException("Unable to convert an image to a video from attachment " + sourceImageAttachment
635 + " using the remote composer service proxy");
636 }
637
638 @Override
639 public Job demux(Track sourceTrack, String profileId) throws EncoderException, MediaPackageException {
640 HttpPost post = new HttpPost("/demux");
641 try {
642 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
643 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
644 params.add(new BasicNameValuePair("profileId", profileId));
645 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
646 } catch (Exception e) {
647 throw new EncoderException("Unable to assemble a remote demux request for track " + sourceTrack, e);
648 }
649 HttpResponse response = null;
650 try {
651 response = getResponse(post);
652 if (response != null) {
653 String content = EntityUtils.toString(response.getEntity());
654 Job r = JobParser.parseJob(content);
655 logger.info("Demuxing job {} started on a remote service ", r.getId());
656 return r;
657 }
658 } catch (Exception e) {
659 throw new EncoderException("Unable to demux track " + sourceTrack + " using a remote composer service", e);
660 } finally {
661 closeConnection(response);
662 }
663 throw new EncoderException("Unable to demux track " + sourceTrack + " using a remote composer service");
664 }
665
666 @Override
667 public Job processSmil(Smil smil, String trackParamGroupId, String mediaType, List<String> profileIds)
668 throws EncoderException, MediaPackageException {
669 HttpPost post = new HttpPost("/processsmil");
670 try {
671 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
672 params.add(new BasicNameValuePair("smilAsXml", smil.toXML()));
673 params.add(new BasicNameValuePair("trackId", trackParamGroupId));
674 params.add(new BasicNameValuePair("mediaType", mediaType));
675 params.add(new BasicNameValuePair("profileIds", StringUtils.join(profileIds, ",")));
676 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
677 } catch (Exception e) {
678 throw new EncoderException(e);
679 }
680 HttpResponse response = null;
681 try {
682 response = getResponse(post);
683 if (response != null) {
684 Job r = JobParser.parseJob(response.getEntity().getContent());
685 logger.info("Concat video job {} started on a remote composer", r.getId());
686 return r;
687 }
688 } catch (Exception e) {
689 throw new EncoderException(e);
690 } finally {
691 closeConnection(response);
692 }
693 throw new EncoderException("Unable to edit video group(" + trackParamGroupId + ") from smil " + smil
694 + " using the remote composer service proxy");
695 }
696
697 @Override
698 public Job multiEncode(Track sourceTrack, List<String> profileIds) throws EncoderException, MediaPackageException {
699 HttpPost post = new HttpPost("/multiencode");
700 try {
701 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
702 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
703 params.add(new BasicNameValuePair("profileIds", StringUtils.join(profileIds, ",")));
704 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
705 } catch (Exception e) {
706 throw new EncoderException("Unable to assemble a remote demux request for track " + sourceTrack, e);
707 }
708 HttpResponse response = null;
709 try {
710 response = getResponse(post);
711 if (response != null) {
712 String content = EntityUtils.toString(response.getEntity());
713 Job job = JobParser.parseJob(content);
714 logger.info("Encoding job {} started on a remote multiencode", job.getId());
715 return job;
716 }
717 } catch (Exception e) {
718 throw new EncoderException("Unable to multiencode track " + sourceTrack + " using a remote composer service", e);
719 } finally {
720 closeConnection(response);
721 }
722 throw new EncoderException("Unable to multiencode track " + sourceTrack + " using a remote composer service");
723 }
724
725
726
727
728
729
730
731
732
733 private String mapToString(Map<String, String> props) {
734 StringBuilder sb = new StringBuilder();
735 for (Entry<String, String> entry : props.entrySet()) {
736 sb.append(entry.getKey());
737 sb.append("=");
738 sb.append(entry.getValue());
739 sb.append("\n");
740 }
741 return sb.toString();
742 }
743
744 }