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 EncodingProfile getProfile(String profileId) {
253 HttpGet get = new HttpGet("/profile/" + profileId + ".xml");
254 HttpResponse response = null;
255 try {
256 response = getResponse(get, HttpStatus.SC_OK, HttpStatus.SC_NOT_FOUND);
257 if (response != null && response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
258 return EncodingProfileBuilder.getInstance().parseProfile(response.getEntity().getContent());
259 } else {
260 return null;
261 }
262 } catch (Exception e) {
263 throw new RuntimeException(e);
264 } finally {
265 closeConnection(response);
266 }
267 }
268
269
270
271
272 @Override
273 public Job image(Track sourceTrack, String profileId, double... times) throws EncoderException {
274 HttpPost post = new HttpPost("/image");
275 try {
276 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
277 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
278 params.add(new BasicNameValuePair("profileId", profileId));
279 params.add(new BasicNameValuePair("time", buildTimeArray(times)));
280 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
281 } catch (Exception e) {
282 throw new EncoderException(e);
283 }
284 HttpResponse response = null;
285 try {
286 response = getResponse(post);
287 if (response != null) {
288 Job r = JobParser.parseJob(response.getEntity().getContent());
289 logger.info("Image extraction job {} started on a remote composer", r.getId());
290 return r;
291 }
292 } catch (Exception e) {
293 throw new EncoderException(e);
294 } finally {
295 closeConnection(response);
296 }
297 throw new EncoderException("Unable to compose an image from track " + sourceTrack
298 + " using the remote composer service proxy");
299 }
300
301 @Override
302 public List<Attachment> imageSync(Track sourceTrack, String profileId, double... times) throws EncoderException, MediaPackageException {
303 HttpPost post = new HttpPost("/imagesync");
304 try {
305 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
306 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
307 params.add(new BasicNameValuePair("profileId", profileId));
308 params.add(new BasicNameValuePair("time", buildTimeArray(times)));
309 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
310 } catch (Exception e) {
311 throw new EncoderException(e);
312 }
313 HttpResponse response = null;
314 try {
315 response = getResponse(post);
316 if (response != null) {
317 final String xml = IOUtils.toString(response.getEntity().getContent(), Charset.forName("utf-8"));
318 return MediaPackageElementParser.getArrayFromXml(xml)
319 .stream().map(e -> (Attachment)e)
320 .collect(Collectors.toList());
321 }
322 } catch (Exception e) {
323 throw new EncoderException(e);
324 } finally {
325 closeConnection(response);
326 }
327 throw new EncoderException("Unable to compose an image from track " + sourceTrack
328 + " using the remote composer service proxy");
329 }
330
331
332
333
334
335
336 @Override
337 public Job image(Track sourceTrack, String profileId, Map<String, String> properties) throws EncoderException,
338 MediaPackageException {
339 HttpPost post = new HttpPost("/image");
340 try {
341 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
342 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
343 params.add(new BasicNameValuePair("profileId", profileId));
344 if (properties != null)
345 params.add(new BasicNameValuePair("properties", mapToString(properties)));
346 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
347 } catch (Exception e) {
348 throw new EncoderException(e);
349 }
350 HttpResponse response = null;
351 try {
352 response = getResponse(post);
353 if (response != null) {
354 Job r = JobParser.parseJob(response.getEntity().getContent());
355 logger.info("Image extraction job {} started on a remote composer", r.getId());
356 return r;
357 }
358 } catch (Exception e) {
359 throw new EncoderException(e);
360 } finally {
361 closeConnection(response);
362 }
363 throw new EncoderException("Unable to compose an image from track " + sourceTrack
364 + " using the remote composer service proxy");
365 }
366
367
368
369
370
371
372
373 @Override
374 public Job convertImage(Attachment image, String... profileIds) throws EncoderException, MediaPackageException {
375 HttpPost post = new HttpPost("/convertimage");
376 try {
377 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
378 params.add(new BasicNameValuePair("sourceImage", MediaPackageElementParser.getAsXml(image)));
379 params.add(new BasicNameValuePair("profileId", StringUtils.join(profileIds, ',')));
380 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
381 } catch (Exception e) {
382 throw new EncoderException(e);
383 }
384 HttpResponse response = null;
385 try {
386 response = getResponse(post);
387 if (response != null) {
388 Job r = JobParser.parseJob(response.getEntity().getContent());
389 logger.info("Image conversion job {} started on a remote composer", r.getId());
390 return r;
391 }
392 } catch (Exception e) {
393 throw new EncoderException(e);
394 } finally {
395 closeConnection(response);
396 }
397 throw new EncoderException("Unable to convert image at " + image + " using the remote composer service proxy");
398 }
399
400
401
402
403
404
405
406 @Override
407 public List<Attachment> convertImageSync(Attachment image, String... profileIds) throws EncoderException, MediaPackageException {
408 HttpPost post = new HttpPost("/convertimagesync");
409 try {
410 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
411 params.add(new BasicNameValuePair("sourceImage", MediaPackageElementParser.getAsXml(image)));
412 params.add(new BasicNameValuePair("profileIds", StringUtils.join(profileIds, ',')));
413 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
414 } catch (Exception e) {
415 throw new EncoderException(e);
416 }
417 HttpResponse response = null;
418 try {
419 response = getResponse(post);
420 if (response != null) {
421 final String xml = IOUtils.toString(response.getEntity().getContent(), Charset.forName("utf-8"));
422 return MediaPackageElementParser.getArrayFromXml(xml).stream().map(a -> (Attachment) a).collect(Collectors.toList());
423 }
424 } catch (Exception e) {
425 throw new EncoderException(e);
426 } finally {
427 closeConnection(response);
428 }
429 throw new EncoderException("Unable to convert image at " + image + " using the remote composer service proxy");
430 }
431
432
433
434
435
436
437 @Override
438 public EncodingProfile[] listProfiles() {
439 HttpGet get = new HttpGet("/profiles.xml");
440 HttpResponse response = null;
441 try {
442 response = getResponse(get);
443 if (response != null) {
444 EncodingProfileList profileList = EncodingProfileBuilder.getInstance().parseProfileList(
445 response.getEntity().getContent());
446 List<EncodingProfileImpl> list = profileList.getProfiles();
447 return list.toArray(new EncodingProfile[list.size()]);
448 }
449 } catch (Exception e) {
450 throw new RuntimeException(
451 "Unable to list the encoding profiles registered with the remote composer service proxy", e);
452 } finally {
453 closeConnection(response);
454 }
455 throw new RuntimeException("Unable to list the encoding profiles registered with the remote composer service proxy");
456 }
457
458
459
460
461
462
463
464
465 protected String buildTimeArray(double[] times) {
466 if (times.length == 0)
467 return "";
468
469 StringBuilder builder = new StringBuilder();
470 builder.append(Double.toString(times[0]));
471 for (int i = 1; i < times.length; i++) {
472 builder.append(";" + Double.toString(times[i]));
473 }
474 return builder.toString();
475 }
476
477 @Override
478 public Job composite(Dimension compositeTrackSize, Option<LaidOutElement<Track>> upperTrack,
479 LaidOutElement<Track> lowerTrack, Option<LaidOutElement<Attachment>> watermark, String profileId,
480 String background, String sourceAudioName) throws EncoderException, MediaPackageException {
481 HttpPost post = new HttpPost("/composite");
482 try {
483 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
484 params.add(new BasicNameValuePair("compositeSize", Serializer.json(compositeTrackSize).toJson()));
485 params.add(new BasicNameValuePair("lowerTrack", MediaPackageElementParser.getAsXml(lowerTrack.getElement())));
486 params.add(new BasicNameValuePair("lowerLayout", Serializer.json(lowerTrack.getLayout()).toJson()));
487 if (upperTrack.isSome()) {
488 params.add(new BasicNameValuePair("upperTrack", MediaPackageElementParser.getAsXml(upperTrack.get()
489 .getElement())));
490 params.add(new BasicNameValuePair("upperLayout", Serializer.json(upperTrack.get().getLayout()).toJson()));
491 }
492
493 if (watermark.isSome()) {
494 params.add(new BasicNameValuePair("watermarkAttachment", MediaPackageElementParser.getAsXml(watermark.get()
495 .getElement())));
496 params.add(new BasicNameValuePair("watermarkLayout", Serializer.json(watermark.get().getLayout()).toJson()));
497 }
498 params.add(new BasicNameValuePair("profileId", profileId));
499 params.add(new BasicNameValuePair("background", background));
500 params.add(new BasicNameValuePair("sourceAudioName", sourceAudioName));
501 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
502 } catch (Exception e) {
503 throw new EncoderException(e);
504 }
505 HttpResponse response = null;
506 try {
507 response = getResponse(post);
508 if (response != null) {
509 Job r = JobParser.parseJob(response.getEntity().getContent());
510 logger.info("Composite video job {} started on a remote composer", r.getId());
511 return r;
512 }
513 } catch (Exception e) {
514 throw new EncoderException(e);
515 } finally {
516 closeConnection(response);
517 }
518 if (upperTrack.isSome()) {
519 throw new EncoderException("Unable to composite video from track " + lowerTrack.getElement() + " and "
520 + upperTrack.get().getElement() + " using the remote composer service proxy");
521 } else {
522 throw new EncoderException("Unable to composite video from track " + lowerTrack.getElement()
523 + " using the remote composer service proxy");
524 }
525 }
526
527 @Override
528 public Job concat(String profileId, Dimension outputDimension, boolean sameCodec, Track... tracks)
529 throws EncoderException, MediaPackageException {
530 return concat(profileId, outputDimension, -1.0f, sameCodec, tracks);
531 }
532
533 @Override
534 public Job concat(String profileId, Dimension outputDimension, float outputFrameRate, boolean sameCodec,
535 Track... tracks)
536 throws EncoderException, MediaPackageException {
537 HttpPost post = new HttpPost("/concat");
538 try {
539 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
540 params.add(new BasicNameValuePair("profileId", profileId));
541 if (outputDimension != null)
542 params.add(new BasicNameValuePair("outputDimension", Serializer.json(outputDimension).toJson()));
543 params.add(new BasicNameValuePair("outputFrameRate", String.format(Locale.US, "%f", outputFrameRate)));
544 params.add(new BasicNameValuePair("sourceTracks", MediaPackageElementParser.getArrayAsXml(Arrays.asList(tracks))));
545 if (sameCodec)
546 params.add(new BasicNameValuePair("sameCodec", "true"));
547 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
548 } catch (Exception e) {
549 throw new EncoderException(e);
550 }
551 HttpResponse response = null;
552 try {
553 response = getResponse(post);
554 if (response != null) {
555 Job r = JobParser.parseJob(response.getEntity().getContent());
556 logger.info("Concat video job {} started on a remote composer", r.getId());
557 return r;
558 }
559 } catch (Exception e) {
560 throw new EncoderException(e);
561 } finally {
562 closeConnection(response);
563 }
564 throw new EncoderException("Unable to concat videos from tracks " + tracks
565 + " using the remote composer service proxy");
566 }
567
568 @Override
569 public Job imageToVideo(Attachment sourceImageAttachment, String profileId, double time) throws EncoderException,
570 MediaPackageException {
571 HttpPost post = new HttpPost("/imagetovideo");
572 try {
573 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
574 params.add(new BasicNameValuePair("sourceAttachment", MediaPackageElementParser.getAsXml(sourceImageAttachment)));
575 params.add(new BasicNameValuePair("profileId", profileId));
576 params.add(new BasicNameValuePair("time", Double.toString(time)));
577 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
578 } catch (Exception e) {
579 throw new EncoderException(e);
580 }
581 HttpResponse response = null;
582 try {
583 response = getResponse(post);
584 if (response != null) {
585 Job r = JobParser.parseJob(response.getEntity().getContent());
586 logger.info("Image to video converting job {} started on a remote composer", r.getId());
587 return r;
588 }
589 } catch (Exception e) {
590 throw new EncoderException(e);
591 } finally {
592 closeConnection(response);
593 }
594 throw new EncoderException("Unable to convert an image to a video from attachment " + sourceImageAttachment
595 + " using the remote composer service proxy");
596 }
597
598 @Override
599 public Job demux(Track sourceTrack, String profileId) throws EncoderException, MediaPackageException {
600 HttpPost post = new HttpPost("/demux");
601 try {
602 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
603 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
604 params.add(new BasicNameValuePair("profileId", profileId));
605 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
606 } catch (Exception e) {
607 throw new EncoderException("Unable to assemble a remote demux request for track " + sourceTrack, e);
608 }
609 HttpResponse response = null;
610 try {
611 response = getResponse(post);
612 if (response != null) {
613 String content = EntityUtils.toString(response.getEntity());
614 Job r = JobParser.parseJob(content);
615 logger.info("Demuxing job {} started on a remote service ", r.getId());
616 return r;
617 }
618 } catch (Exception e) {
619 throw new EncoderException("Unable to demux track " + sourceTrack + " using a remote composer service", e);
620 } finally {
621 closeConnection(response);
622 }
623 throw new EncoderException("Unable to demux track " + sourceTrack + " using a remote composer service");
624 }
625
626 @Override
627 public Job processSmil(Smil smil, String trackParamGroupId, String mediaType, List<String> profileIds)
628 throws EncoderException, MediaPackageException {
629 HttpPost post = new HttpPost("/processsmil");
630 try {
631 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
632 params.add(new BasicNameValuePair("smilAsXml", smil.toXML()));
633 params.add(new BasicNameValuePair("trackId", trackParamGroupId));
634 params.add(new BasicNameValuePair("mediaType", mediaType));
635 params.add(new BasicNameValuePair("profileIds", StringUtils.join(profileIds, ",")));
636 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
637 } catch (Exception e) {
638 throw new EncoderException(e);
639 }
640 HttpResponse response = null;
641 try {
642 response = getResponse(post);
643 if (response != null) {
644 Job r = JobParser.parseJob(response.getEntity().getContent());
645 logger.info("Concat video job {} started on a remote composer", r.getId());
646 return r;
647 }
648 } catch (Exception e) {
649 throw new EncoderException(e);
650 } finally {
651 closeConnection(response);
652 }
653 throw new EncoderException("Unable to edit video group(" + trackParamGroupId + ") from smil " + smil
654 + " using the remote composer service proxy");
655 }
656
657 @Override
658 public Job multiEncode(Track sourceTrack, List<String> profileIds) throws EncoderException, MediaPackageException {
659 HttpPost post = new HttpPost("/multiencode");
660 try {
661 List<BasicNameValuePair> params = new ArrayList<BasicNameValuePair>();
662 params.add(new BasicNameValuePair("sourceTrack", MediaPackageElementParser.getAsXml(sourceTrack)));
663 params.add(new BasicNameValuePair("profileIds", StringUtils.join(profileIds, ",")));
664 post.setEntity(new UrlEncodedFormEntity(params, "UTF-8"));
665 } catch (Exception e) {
666 throw new EncoderException("Unable to assemble a remote demux request for track " + sourceTrack, e);
667 }
668 HttpResponse response = null;
669 try {
670 response = getResponse(post);
671 if (response != null) {
672 String content = EntityUtils.toString(response.getEntity());
673 Job job = JobParser.parseJob(content);
674 logger.info("Encoding job {} started on a remote multiencode", job.getId());
675 return job;
676 }
677 } catch (Exception e) {
678 throw new EncoderException("Unable to multiencode track " + sourceTrack + " using a remote composer service", e);
679 } finally {
680 closeConnection(response);
681 }
682 throw new EncoderException("Unable to multiencode track " + sourceTrack + " using a remote composer service");
683 }
684
685
686
687
688
689
690
691
692
693 private String mapToString(Map<String, String> props) {
694 StringBuilder sb = new StringBuilder();
695 for (Entry<String, String> entry : props.entrySet()) {
696 sb.append(entry.getKey());
697 sb.append("=");
698 sb.append(entry.getValue());
699 sb.append("\n");
700 }
701 return sb.toString();
702 }
703
704 }