use of org.opencastproject.workflow.api.WorkflowOperationResult in project opencast by opencast.
the class ConcatWorkflowOperationHandlerTest method testConcat2EncodedTracksWithTags.
@Test
public void testConcat2EncodedTracksWithTags() throws Exception {
setMockups();
// operation configuration
String targetTags = "engage,rss";
Map<String, String> configurations = new HashMap<String, String>();
configurations.put("source-flavor-part-0", "presentation/source");
configurations.put("source-flavor-part-1", "presenter/source");
configurations.put("source-tags-part-0", "part0,part0b");
configurations.put("source-tags-part-1", "part1");
configurations.put("target-tags", targetTags);
configurations.put("target-flavor", "presenter/concat");
configurations.put("encoding-profile", "concat");
configurations.put("output-resolution", "1900x1080");
// run the operation handler
WorkflowOperationResult result = getWorkflowOperationResult(mp, configurations);
// check track metadata
MediaPackage mpNew = result.getMediaPackage();
Track trackEncoded = mpNew.getTrack(ENCODED_TRACK_ID);
Assert.assertEquals("presenter/concat", trackEncoded.getFlavor().toString());
Assert.assertArrayEquals(targetTags.split("\\W"), trackEncoded.getTags());
}
use of org.opencastproject.workflow.api.WorkflowOperationResult in project opencast by opencast.
the class ConcatWorkflowOperationHandlerTest method createTestFrameRateWithValue.
protected void createTestFrameRateWithValue(String frameRateValue, float expectedFrameRateValue) throws Exception {
setMockupsWithFrameRate(expectedFrameRateValue);
// operation configuration
String targetTags = "engage,rss";
Map<String, String> configurations = new HashMap<String, String>();
configurations.put("source-flavor-part-0", "presentation/source");
configurations.put("source-flavor-part-1", "presenter/source");
configurations.put("source-flavor-part-1-mandatory", "true");
configurations.put("target-tags", targetTags);
configurations.put("target-flavor", "presenter/concat");
configurations.put("encoding-profile", "concat");
configurations.put("output-resolution", "part-1");
configurations.put("output-framerate", frameRateValue);
// run the operation handler
WorkflowOperationResult result = getWorkflowOperationResult(mp, configurations);
// check track metadata
MediaPackage mpNew = result.getMediaPackage();
Track trackEncoded = mpNew.getTrack(ENCODED_TRACK_ID);
Assert.assertEquals("presenter/concat", trackEncoded.getFlavor().toString());
Assert.assertArrayEquals(targetTags.split("\\W"), trackEncoded.getTags());
}
use of org.opencastproject.workflow.api.WorkflowOperationResult in project opencast by opencast.
the class ConcatWorkflowOperationHandler method concat.
private WorkflowOperationResult concat(MediaPackage src, WorkflowOperationInstance operation) throws EncoderException, IOException, NotFoundException, MediaPackageException, WorkflowOperationException {
MediaPackage mediaPackage = (MediaPackage) src.clone();
Map<Integer, Tuple<TrackSelector, Boolean>> trackSelectors = getTrackSelectors(operation);
String outputResolution = StringUtils.trimToNull(operation.getConfiguration(OUTPUT_RESOLUTION));
String outputFrameRate = StringUtils.trimToNull(operation.getConfiguration(OUTPUT_FRAMERATE));
String encodingProfile = StringUtils.trimToNull(operation.getConfiguration(ENCODING_PROFILE));
// Skip the worklow if no source-flavors or tags has been configured
if (trackSelectors.isEmpty()) {
logger.warn("No source-tags or source-flavors has been set.");
return createResult(mediaPackage, Action.SKIP);
}
String targetTagsOption = StringUtils.trimToNull(operation.getConfiguration(TARGET_TAGS));
String targetFlavorOption = StringUtils.trimToNull(operation.getConfiguration(TARGET_FLAVOR));
// Target tags
List<String> targetTags = asList(targetTagsOption);
// Target flavor
if (targetFlavorOption == null)
throw new WorkflowOperationException("Target flavor must be set!");
// Find the encoding profile
if (encodingProfile == null)
throw new WorkflowOperationException("Encoding profile must be set!");
EncodingProfile profile = composerService.getProfile(encodingProfile);
if (profile == null)
throw new WorkflowOperationException("Encoding profile '" + encodingProfile + "' was not found");
// Output resolution
if (outputResolution == null)
throw new WorkflowOperationException("Output resolution must be set!");
Dimension outputDimension = null;
if (outputResolution.startsWith(OUTPUT_PART_PREFIX)) {
if (!trackSelectors.keySet().contains(Integer.parseInt(outputResolution.substring(OUTPUT_PART_PREFIX.length()))))
throw new WorkflowOperationException("Output resolution part not set!");
} else {
try {
String[] outputResolutionArray = StringUtils.split(outputResolution, "x");
if (outputResolutionArray.length != 2) {
throw new WorkflowOperationException("Invalid format of output resolution!");
}
outputDimension = Dimension.dimension(Integer.parseInt(outputResolutionArray[0]), Integer.parseInt(outputResolutionArray[1]));
} catch (WorkflowOperationException e) {
throw e;
} catch (Exception e) {
throw new WorkflowOperationException("Unable to parse output resolution!", e);
}
}
float fps = -1.0f;
if (StringUtils.isNotEmpty(outputFrameRate)) {
if (StringUtils.startsWith(outputFrameRate, OUTPUT_PART_PREFIX)) {
if (!NumberUtils.isNumber(outputFrameRate.substring(OUTPUT_PART_PREFIX.length())) || !trackSelectors.keySet().contains(Integer.parseInt(outputFrameRate.substring(OUTPUT_PART_PREFIX.length())))) {
throw new WorkflowOperationException("Output frame rate part not set or invalid!");
}
} else if (NumberUtils.isNumber(outputFrameRate)) {
fps = NumberUtils.toFloat(outputFrameRate);
} else {
throw new WorkflowOperationException("Unable to parse output frame rate!");
}
}
MediaPackageElementFlavor targetFlavor = null;
try {
targetFlavor = MediaPackageElementFlavor.parseFlavor(targetFlavorOption);
if ("*".equals(targetFlavor.getType()) || "*".equals(targetFlavor.getSubtype()))
throw new WorkflowOperationException("Target flavor must have a type and a subtype, '*' are not allowed!");
} catch (IllegalArgumentException e) {
throw new WorkflowOperationException("Target flavor '" + targetFlavorOption + "' is malformed");
}
List<Track> tracks = new ArrayList<Track>();
for (Entry<Integer, Tuple<TrackSelector, Boolean>> trackSelector : trackSelectors.entrySet()) {
Collection<Track> tracksForSelector = trackSelector.getValue().getA().select(mediaPackage, false);
String currentFlavor = StringUtils.join(trackSelector.getValue().getA().getFlavors());
String currentTag = StringUtils.join(trackSelector.getValue().getA().getTags());
if (tracksForSelector.size() > 1) {
logger.warn("More than one track has been found with flavor '{}' and/or tag '{}' for concat operation, skipping concatenation!", currentFlavor, currentTag);
return createResult(mediaPackage, Action.SKIP);
} else if (tracksForSelector.size() == 0 && trackSelector.getValue().getB()) {
logger.warn("No track has been found with flavor '{}' and/or tag '{}' for concat operation, skipping concatenation!", currentFlavor, currentTag);
return createResult(mediaPackage, Action.SKIP);
} else if (tracksForSelector.size() == 0 && !trackSelector.getValue().getB()) {
logger.info("No track has been found with flavor '{}' and/or tag '{}' for concat operation, skipping track!", currentFlavor, currentTag);
continue;
}
for (Track t : tracksForSelector) {
tracks.add(t);
VideoStream[] videoStreams = TrackSupport.byType(t.getStreams(), VideoStream.class);
if (videoStreams.length == 0) {
logger.info("No video stream available in the track with flavor {}! {}", currentFlavor, t);
return createResult(mediaPackage, Action.SKIP);
}
if (StringUtils.startsWith(outputResolution, OUTPUT_PART_PREFIX) && NumberUtils.isNumber(outputResolution.substring(OUTPUT_PART_PREFIX.length())) && trackSelector.getKey() == Integer.parseInt(outputResolution.substring(OUTPUT_PART_PREFIX.length()))) {
outputDimension = new Dimension(videoStreams[0].getFrameWidth(), videoStreams[0].getFrameHeight());
if (!trackSelector.getValue().getB()) {
logger.warn("Output resolution track {} must be mandatory, skipping concatenation!", outputResolution);
return createResult(mediaPackage, Action.SKIP);
}
}
if (fps <= 0 && StringUtils.startsWith(outputFrameRate, OUTPUT_PART_PREFIX) && NumberUtils.isNumber(outputFrameRate.substring(OUTPUT_PART_PREFIX.length())) && trackSelector.getKey() == Integer.parseInt(outputFrameRate.substring(OUTPUT_PART_PREFIX.length()))) {
fps = videoStreams[0].getFrameRate();
}
}
}
if (tracks.size() == 0) {
logger.warn("No tracks found for concating operation, skipping concatenation!");
return createResult(mediaPackage, Action.SKIP);
} else if (tracks.size() == 1) {
Track track = (Track) tracks.get(0).clone();
track.setIdentifier(null);
addNewTrack(mediaPackage, track, targetTags, targetFlavor);
logger.info("At least two tracks are needed for the concating operation, skipping concatenation!");
return createResult(mediaPackage, Action.SKIP);
}
Job concatJob;
if (fps > 0) {
concatJob = composerService.concat(profile.getIdentifier(), outputDimension, fps, tracks.toArray(new Track[tracks.size()]));
} else {
concatJob = composerService.concat(profile.getIdentifier(), outputDimension, tracks.toArray(new Track[tracks.size()]));
}
// Wait for the jobs to return
if (!waitForStatus(concatJob).isSuccess())
throw new WorkflowOperationException("The concat job did not complete successfully");
if (concatJob.getPayload().length() > 0) {
Track concatTrack = (Track) MediaPackageElementParser.getFromXml(concatJob.getPayload());
concatTrack.setURI(workspace.moveTo(concatTrack.getURI(), mediaPackage.getIdentifier().toString(), concatTrack.getIdentifier(), "concat." + FilenameUtils.getExtension(concatTrack.getURI().toString())));
addNewTrack(mediaPackage, concatTrack, targetTags, targetFlavor);
WorkflowOperationResult result = createResult(mediaPackage, Action.CONTINUE, concatJob.getQueueTime());
logger.debug("Concat operation completed");
return result;
} else {
logger.info("concat operation unsuccessful, no payload returned: {}", concatJob);
return createResult(mediaPackage, Action.SKIP);
}
}
use of org.opencastproject.workflow.api.WorkflowOperationResult in project opencast by opencast.
the class VideoEditorWorkflowOperationHandlerTest method testEditorResume.
@Test
public void testEditorResume() throws WorkflowOperationException, URISyntaxException, NotFoundException, IOException, ProcessFailedException, ServiceRegistryException, MediaPackageException {
// filled smil file
URI episodeSmilURI = VideoEditorWorkflowOperationHandlerTest.class.getResource("/editor_smil_filled.smil").toURI();
File episodeSmilFile = new File(episodeSmilURI);
// setup mock services
EasyMock.expect(workspaceMock.get((URI) EasyMock.anyObject())).andReturn(episodeSmilFile);
EasyMock.expect(workspaceMock.put((String) EasyMock.anyObject(), (String) EasyMock.anyObject(), (String) EasyMock.anyObject(), (InputStream) EasyMock.anyObject())).andReturn(episodeSmilURI);
EasyMock.expect(workspaceMock.moveTo((URI) EasyMock.anyObject(), (String) EasyMock.anyObject(), (String) EasyMock.anyObject(), (String) EasyMock.anyObject())).andReturn(URI.create("http://localhost:8080/foo/trimmed.mp4"));
Job job = EasyMock.createNiceMock(Job.class);
EasyMock.expect(job.getPayload()).andReturn(MediaPackageElementParser.getAsXml(mpSmil.getTracks()[0])).anyTimes();
EasyMock.expect(job.getStatus()).andReturn(Job.Status.FINISHED);
ServiceRegistry serviceRegistry = EasyMock.createNiceMock(ServiceRegistry.class);
videoEditorWorkflowOperationHandler.setServiceRegistry(serviceRegistry);
EasyMock.expect(serviceRegistry.getJob(EasyMock.anyLong())).andReturn(job);
EasyMock.expect(videoEditorServiceMock.processSmil((Smil) EasyMock.anyObject())).andReturn(Arrays.asList(job));
EasyMock.replay(workspaceMock, job, serviceRegistry, videoEditorServiceMock);
WorkflowInstanceImpl workflowInstance = getWorkflowInstance(mpSmil, getDefaultConfiguration(true));
// run test
WorkflowOperationResult result = videoEditorWorkflowOperationHandler.resume(workflowInstance, null, null);
Assert.assertNotNull("VideoEditor workflow operation returns null but should be an instantiated WorkflowOperationResult", result);
EasyMock.verify(workspaceMock, job, serviceRegistry, videoEditorServiceMock);
// verify trimmed track derived from source track
WorkflowOperationInstance worflowOperationInstance = workflowInstance.getCurrentOperation();
String targetFlavorSubtypeProperty = worflowOperationInstance.getConfiguration("target-flavor-subtype");
String sourceFlavorsProperty = worflowOperationInstance.getConfiguration("source-flavors");
TrackSelector trackSelector = new TrackSelector();
trackSelector.addFlavor(sourceFlavorsProperty);
Collection<Track> sourceTracks = trackSelector.select(result.getMediaPackage(), false);
Assert.assertTrue("Mediapackage does not contain any tracks matching flavor " + sourceFlavorsProperty, sourceTracks != null && !sourceTracks.isEmpty());
for (Track sourceTrack : sourceTracks) {
MediaPackageElementFlavor targetFlavor = MediaPackageElementFlavor.flavor(sourceTrack.getFlavor().getType(), targetFlavorSubtypeProperty);
Track[] targetTracks = result.getMediaPackage().getTracks(targetFlavor);
Assert.assertTrue("Media package doesn't contain track with flavor " + targetFlavor.toString(), targetTracks != null && targetTracks.length > 0);
}
}
use of org.opencastproject.workflow.api.WorkflowOperationResult in project opencast by opencast.
the class ConfigurablePublishWorkflowOperationHandlerTest method testNormal.
@Test
public void testNormal() throws WorkflowOperationException, URISyntaxException, DistributionException, MediaPackageException {
String channelId = "engage-player";
String attachmentId = "attachment-id";
String catalogId = "catalog-id";
String trackId = "track-id";
Attachment attachment = new AttachmentImpl();
attachment.addTag("engage-download");
attachment.setIdentifier(attachmentId);
attachment.setURI(new URI("http://api.com/attachment"));
Catalog catalog = CatalogImpl.newInstance();
catalog.addTag("engage-download");
catalog.setIdentifier(catalogId);
catalog.setURI(new URI("http://api.com/catalog"));
Track track = new TrackImpl();
track.addTag("engage-streaming");
track.setIdentifier(trackId);
track.setURI(new URI("http://api.com/track"));
Publication publicationtest = new PublicationImpl(trackId, channelId, new URI("http://api.com/publication"), MimeType.mimeType(trackId, trackId));
Track unrelatedTrack = new TrackImpl();
unrelatedTrack.addTag("unrelated");
Capture<MediaPackageElement> capturePublication = Capture.newInstance();
MediaPackage mediapackageClone = EasyMock.createNiceMock(MediaPackage.class);
EasyMock.expect(mediapackageClone.getElements()).andStubReturn(new MediaPackageElement[] { attachment, catalog, track, unrelatedTrack });
EasyMock.expect(mediapackageClone.getIdentifier()).andStubReturn(new IdImpl("mp-id-clone"));
EasyMock.expectLastCall();
EasyMock.replay(mediapackageClone);
MediaPackage mediapackage = EasyMock.createNiceMock(MediaPackage.class);
EasyMock.expect(mediapackage.getElements()).andStubReturn(new MediaPackageElement[] { attachment, catalog, track, unrelatedTrack });
EasyMock.expect(mediapackage.clone()).andStubReturn(mediapackageClone);
EasyMock.expect(mediapackage.getIdentifier()).andStubReturn(new IdImpl("mp-id"));
mediapackage.add(EasyMock.capture(capturePublication));
mediapackage.add(publicationtest);
EasyMock.expect(mediapackage.getPublications()).andStubReturn(new Publication[] { publicationtest });
EasyMock.expectLastCall();
EasyMock.replay(mediapackage);
WorkflowOperationInstance op = EasyMock.createNiceMock(WorkflowOperationInstance.class);
EasyMock.expect(op.getConfiguration(ConfigurablePublishWorkflowOperationHandler.CHANNEL_ID_KEY)).andStubReturn(channelId);
EasyMock.expect(op.getConfiguration(ConfigurablePublishWorkflowOperationHandler.MIME_TYPE)).andStubReturn("text/html");
EasyMock.expect(op.getConfiguration(ConfigurablePublishWorkflowOperationHandler.URL_PATTERN)).andStubReturn("http://api.opencast.org/api/events/${event_id}");
EasyMock.expect(op.getConfiguration(ConfigurablePublishWorkflowOperationHandler.SOURCE_TAGS)).andStubReturn("engage-download,engage-streaming");
EasyMock.expect(op.getConfiguration(ConfigurablePublishWorkflowOperationHandler.CHECK_AVAILABILITY)).andStubReturn("true");
EasyMock.expect(op.getConfiguration(ConfigurablePublishWorkflowOperationHandler.STRATEGY)).andStubReturn("retract");
EasyMock.expect(op.getConfiguration(ConfigurablePublishWorkflowOperationHandler.MODE)).andStubReturn("single");
EasyMock.replay(op);
WorkflowInstance workflowInstance = EasyMock.createNiceMock(WorkflowInstance.class);
EasyMock.expect(workflowInstance.getMediaPackage()).andStubReturn(mediapackage);
EasyMock.expect(workflowInstance.getCurrentOperation()).andStubReturn(op);
EasyMock.replay(workflowInstance);
JobContext jobContext = EasyMock.createNiceMock(JobContext.class);
EasyMock.replay(jobContext);
Job attachmentJob = EasyMock.createNiceMock(Job.class);
EasyMock.expect(attachmentJob.getPayload()).andReturn(MediaPackageElementParser.getAsXml(attachment));
EasyMock.replay(attachmentJob);
Job catalogJob = EasyMock.createNiceMock(Job.class);
EasyMock.expect(catalogJob.getPayload()).andReturn(MediaPackageElementParser.getAsXml(catalog));
EasyMock.replay(catalogJob);
Job trackJob = EasyMock.createNiceMock(Job.class);
EasyMock.expect(trackJob.getPayload()).andReturn(MediaPackageElementParser.getAsXml(track));
EasyMock.replay(trackJob);
Job retractJob = EasyMock.createNiceMock(Job.class);
EasyMock.expect(retractJob.getPayload()).andReturn(MediaPackageElementParser.getAsXml(track));
EasyMock.replay(retractJob);
DownloadDistributionService distributionService = EasyMock.createNiceMock(DownloadDistributionService.class);
// Make sure that all of the elements are distributed.
EasyMock.expect(distributionService.distribute(channelId, mediapackage, attachmentId, true)).andReturn(attachmentJob);
EasyMock.expect(distributionService.distribute(channelId, mediapackage, catalogId, true)).andReturn(catalogJob);
EasyMock.expect(distributionService.distribute(channelId, mediapackage, trackId, true)).andReturn(trackJob);
EasyMock.expect(distributionService.retract(channelId, mediapackage, channelId)).andReturn(retractJob);
EasyMock.replay(distributionService);
SecurityService securityService = EasyMock.createNiceMock(SecurityService.class);
EasyMock.expect(securityService.getOrganization()).andStubReturn(org);
EasyMock.replay(securityService);
ServiceRegistry serviceRegistry = EasyMock.createNiceMock(ServiceRegistry.class);
EasyMock.replay(serviceRegistry);
// Override the waitForStatus method to not block the jobs
ConfigurablePublishWorkflowOperationHandler configurePublish = new ConfigurablePublishWorkflowOperationHandler() {
@Override
protected Result waitForStatus(long timeout, Job... jobs) {
HashMap<Job, Status> map = Stream.mk(jobs).foldl(new HashMap<Job, Status>(), new Fn2<HashMap<Job, Status>, Job, HashMap<Job, Status>>() {
@Override
public HashMap<Job, Status> apply(HashMap<Job, Status> a, Job b) {
a.put(b, Status.FINISHED);
return a;
}
});
return new Result(map);
}
};
configurePublish.setDownloadDistributionService(distributionService);
configurePublish.setSecurityService(securityService);
configurePublish.setServiceRegistry(serviceRegistry);
WorkflowOperationResult result = configurePublish.start(workflowInstance, jobContext);
assertNotNull(result.getMediaPackage());
assertTrue("The publication element has not been added to the mediapackage.", capturePublication.hasCaptured());
assertTrue("Some other type of element has been added to the mediapackage instead of the publication element.", capturePublication.getValue().getElementType().equals(MediaPackageElement.Type.Publication));
Publication publication = (Publication) capturePublication.getValue();
assertEquals(1, publication.getAttachments().length);
assertNotEquals(attachment.getIdentifier(), publication.getAttachments()[0].getIdentifier());
attachment.setIdentifier(publication.getAttachments()[0].getIdentifier());
assertEquals(attachment, publication.getAttachments()[0]);
assertEquals(1, publication.getCatalogs().length);
assertNotEquals(catalog.getIdentifier(), publication.getCatalogs()[0].getIdentifier());
catalog.setIdentifier(publication.getCatalogs()[0].getIdentifier());
assertEquals(catalog, publication.getCatalogs()[0]);
assertEquals(1, publication.getTracks().length);
assertNotEquals(track.getIdentifier(), publication.getTracks()[0].getIdentifier());
track.setIdentifier(publication.getTracks()[0].getIdentifier());
assertEquals(track, publication.getTracks()[0]);
}
Aggregations