use of org.opencastproject.mediapackage.Track in project opencast by opencast.
the class WorkflowInstanceTest method testFlavorMarshalling.
@Test
public void testFlavorMarshalling() throws Exception {
URI uri = new URI("http://testing");
Track track = TrackImpl.fromURI(uri);
track.setFlavor(MediaPackageElements.PRESENTATION_SOURCE);
MediaPackage mp = MediaPackageBuilderFactory.newInstance().newMediaPackageBuilder().createNew();
mp.add(track);
WorkflowInstance workflow = new WorkflowInstanceImpl();
workflow.setMediaPackage(mp);
// Marshall the workflow to xml
String xml = WorkflowParser.toXml(workflow);
// Get it back from xml
WorkflowInstance instance2 = WorkflowParser.parseWorkflowInstance(xml);
Assert.assertEquals(workflow.getMediaPackage().getTracks()[0].getFlavor(), instance2.getMediaPackage().getTracks()[0].getFlavor());
String namespaceXml = "<workflow xmlns=\"http://workflow.opencastproject.org\" xmlns:mp=\"http://mediapackage.opencastproject.org\"><parent/><mp:mediapackage><mp:media><mp:track type=\"presentation/source\" id=\"track-1\"><mp:url>http://testing</mp:url></mp:track></mp:media></mp:mediapackage></workflow>";
WorkflowInstance instance3 = WorkflowParser.parseWorkflowInstance(namespaceXml);
Assert.assertEquals(workflow.getMediaPackage().getTracks()[0].getFlavor(), instance3.getMediaPackage().getTracks()[0].getFlavor());
}
use of org.opencastproject.mediapackage.Track in project opencast by opencast.
the class ProbeResolutionWorkflowOperationHandler method start.
@Override
public WorkflowOperationResult start(WorkflowInstance workflowInstance, JobContext context) throws WorkflowOperationException {
logger.info("Running probe-resolution workflow operation");
final MediaPackage mediaPackage = workflowInstance.getMediaPackage();
final String sourceFlavorName = getConfig(workflowInstance, OPT_SOURCE_FLAVOR);
final MediaPackageElementFlavor sourceFlavor = MediaPackageElementFlavor.parseFlavor(sourceFlavorName);
// Ensure we have a matching track
final Track[] tracks = mediaPackage.getTracks(sourceFlavor);
if (tracks.length <= 0) {
logger.info("No tracks with specified flavor ({}).", sourceFlavorName);
return createResult(mediaPackage, Action.CONTINUE);
}
// Create mapping: resolution -> [varNames]
Map<Fraction, Set<String>> resolutionMapping = new HashMap<>();
for (String key : workflowInstance.getCurrentOperation().getConfigurationKeys()) {
if (key.startsWith(OPT_VAR_PREFIX)) {
String varName = key.substring(OPT_VAR_PREFIX.length());
for (Fraction resolution : getResolutions(getConfig(workflowInstance, key))) {
if (!resolutionMapping.containsKey(resolution)) {
resolutionMapping.put(resolution, new HashSet<String>());
}
resolutionMapping.get(resolution).add(varName);
}
}
}
// Create mapping: varName -> value
Map<String, String> valueMapping = new HashMap<>();
for (String key : workflowInstance.getCurrentOperation().getConfigurationKeys()) {
if (key.startsWith(OPT_VAL_PREFIX)) {
String varName = key.substring(OPT_VAL_PREFIX.length());
valueMapping.put(varName, getConfig(workflowInstance, key));
}
}
Map<String, String> properties = new HashMap<String, String>();
for (Track track : tracks) {
final String flavor = toVariableName(track.getFlavor());
// Check if resolution fits
if (track.hasVideo()) {
for (VideoStream video : ((TrackImpl) track).getVideo()) {
Fraction resolution = Fraction.getFraction(video.getFrameWidth(), video.getFrameHeight());
if (resolutionMapping.containsKey(resolution)) {
for (String varName : resolutionMapping.get(resolution)) {
String value = valueMapping.containsKey(varName) ? valueMapping.get(varName) : "true";
properties.put(flavor + varName, value);
}
}
}
}
}
logger.info("Finished workflow operation adding the properties: {}", properties);
return createResult(mediaPackage, properties, Action.CONTINUE, 0);
}
use of org.opencastproject.mediapackage.Track in project opencast by opencast.
the class VideoEditorWorkflowOperationHandler method resume.
/**
* {@inheritDoc}
*
* @see org.opencastproject.workflow.api.ResumableWorkflowOperationHandler#resume(org.opencastproject.workflow.api.WorkflowInstance,
* JobContext, java.util.Map)
*/
@Override
public WorkflowOperationResult resume(WorkflowInstance workflowInstance, JobContext context, Map<String, String> properties) throws WorkflowOperationException {
MediaPackage mp = workflowInstance.getMediaPackage();
logger.info("Resume video editor operation for mediapackage {}", mp.getIdentifier().compact());
// Get configuration
WorkflowOperationInstance worflowOperationInstance = workflowInstance.getCurrentOperation();
String sourceTrackFlavorsProperty = StringUtils.trimToNull(worflowOperationInstance.getConfiguration(SOURCE_FLAVORS_PROPERTY));
if (sourceTrackFlavorsProperty == null) {
throw new WorkflowOperationException(format("Required configuration property %s not set.", SOURCE_FLAVORS_PROPERTY));
}
String targetSmilFlavorProperty = StringUtils.trimToNull(worflowOperationInstance.getConfiguration(TARGET_SMIL_FLAVOR_PROPERTY));
if (targetSmilFlavorProperty == null) {
throw new WorkflowOperationException(format("Required configuration property %s not set.", TARGET_SMIL_FLAVOR_PROPERTY));
}
String targetFlavorSybTypeProperty = StringUtils.trimToNull(worflowOperationInstance.getConfiguration(TARGET_FLAVOR_SUBTYPE_PROPERTY));
if (targetFlavorSybTypeProperty == null) {
throw new WorkflowOperationException(format("Required configuration property %s not set.", TARGET_FLAVOR_SUBTYPE_PROPERTY));
}
boolean skipIfNoTrim = BooleanUtils.toBoolean(worflowOperationInstance.getConfiguration(SKIP_NOT_TRIMMED_PROPERTY));
// Get source tracks
TrackSelector trackSelector = new TrackSelector();
for (String flavor : asList(sourceTrackFlavorsProperty)) {
trackSelector.addFlavor(flavor);
}
Collection<Track> sourceTracks = trackSelector.select(mp, false);
if (sourceTracks.isEmpty()) {
throw new WorkflowOperationException(format("No source tracks found in mediapacksge %s with flavors %s.", mp.getIdentifier().compact(), sourceTrackFlavorsProperty));
}
// Get SMIL file
MediaPackageElementFlavor smilTargetFlavor = MediaPackageElementFlavor.parseFlavor(targetSmilFlavorProperty);
Catalog[] smilCatalogs = mp.getCatalogs(smilTargetFlavor);
if (smilCatalogs == null || smilCatalogs.length == 0) {
throw new WorkflowOperationException(format("No SMIL catalog found in mediapackage %s with flavor %s.", mp.getIdentifier().compact(), targetSmilFlavorProperty));
}
File smilFile = null;
Smil smil = null;
try {
smilFile = workspace.get(smilCatalogs[0].getURI());
smil = smilService.fromXml(smilFile).getSmil();
smil = replaceAllTracksWith(smil, sourceTracks.toArray(new Track[sourceTracks.size()]));
InputStream is = null;
try {
is = IOUtils.toInputStream(smil.toXML(), "UTF-8");
// Remove old SMIL
workspace.delete(mp.getIdentifier().compact(), smilCatalogs[0].getIdentifier());
mp.remove(smilCatalogs[0]);
// put modified SMIL into workspace
URI newSmilUri = workspace.put(mp.getIdentifier().compact(), smil.getId(), SMIL_FILE_NAME, is);
Catalog catalog = (Catalog) MediaPackageElementBuilderFactory.newInstance().newElementBuilder().elementFromURI(newSmilUri, MediaPackageElement.Type.Catalog, smilCatalogs[0].getFlavor());
catalog.setIdentifier(smil.getId());
mp.add(catalog);
} catch (Exception ex) {
throw new WorkflowOperationException(ex);
} finally {
IOUtils.closeQuietly(is);
}
} catch (NotFoundException ex) {
throw new WorkflowOperationException(format("Failed to get SMIL catalog %s from mediapackage %s.", smilCatalogs[0].getIdentifier(), mp.getIdentifier().compact()), ex);
} catch (IOException ex) {
throw new WorkflowOperationException(format("Can't open SMIL catalog %s from mediapackage %s.", smilCatalogs[0].getIdentifier(), mp.getIdentifier().compact()), ex);
} catch (SmilException ex) {
throw new WorkflowOperationException(ex);
}
if (skipIfNoTrim) {
// We should not modify the SMIL file as we traverse through its elements, so we make a copy and modify it instead
try {
Smil filteredSmil = smilService.fromXml(smil.toXML()).getSmil();
for (SmilMediaObject element : smil.getBody().getMediaElements()) {
// body should contain par elements
if (element.isContainer()) {
SmilMediaContainer container = (SmilMediaContainer) element;
if (SmilMediaContainer.ContainerType.PAR == container.getContainerType()) {
continue;
}
}
filteredSmil = smilService.removeSmilElement(filteredSmil, element.getId()).getSmil();
}
// one that takes the whole video size
switch(filteredSmil.getBody().getMediaElements().size()) {
case 0:
logger.info("Skipping SMIL job generation for mediapackage '{}', " + "because the SMIL does not define any trimming points", mp.getIdentifier());
return skip(workflowInstance, context);
case 1:
// component represents the whole duration or not, therefore we don't bother to try
if (mp.getDuration() < 0)
break;
SmilMediaContainer parElement = (SmilMediaContainer) filteredSmil.getBody().getMediaElements().get(0);
boolean skip = true;
for (SmilMediaObject elementChild : parElement.getElements()) {
if (!elementChild.isContainer()) {
SmilMediaElement media = (SmilMediaElement) elementChild;
// If they don't represent the whole length, then we break --we have a trimming point
if ((media.getClipBeginMS() != 0) || (media.getClipEndMS() != mp.getDuration())) {
skip = false;
break;
}
}
}
if (skip) {
logger.info("Skipping SMIL job generation for mediapackage '{}', " + "because the trimming points in the SMIL correspond " + "to the beginning and the end of the video", mp.getIdentifier());
return skip(workflowInstance, context);
}
break;
default:
break;
}
} catch (MalformedURLException | SmilException | JAXBException | SAXException e) {
logger.warn("Error parsing input SMIL to determine if it has trimpoints. " + "We will assume it does and go on creating jobs.");
}
}
// Create video edit jobs and run them
List<Job> jobs = null;
try {
logger.info("Create processing jobs for SMIL file: {}", smilCatalogs[0].getIdentifier());
jobs = videoEditorService.processSmil(smil);
if (!waitForStatus(jobs.toArray(new Job[jobs.size()])).isSuccess()) {
throw new WorkflowOperationException(format("Processing SMIL file failed: %s", smilCatalogs[0].getIdentifier()));
}
logger.info("Finished processing of SMIL file: {}", smilCatalogs[0].getIdentifier());
} catch (ProcessFailedException ex) {
throw new WorkflowOperationException(format("Finished processing of SMIL file: %s", smilCatalogs[0].getIdentifier()), ex);
}
// Move edited tracks to work location and set target flavor
Track editedTrack = null;
boolean mpAdded = false;
for (Job job : jobs) {
try {
editedTrack = (Track) MediaPackageElementParser.getFromXml(job.getPayload());
MediaPackageElementFlavor editedTrackFlavor = editedTrack.getFlavor();
editedTrack.setFlavor(new MediaPackageElementFlavor(editedTrackFlavor.getType(), targetFlavorSybTypeProperty));
URI editedTrackNewUri = workspace.moveTo(editedTrack.getURI(), mp.getIdentifier().compact(), editedTrack.getIdentifier(), FilenameUtils.getName(editedTrack.getURI().toString()));
editedTrack.setURI(editedTrackNewUri);
for (Track track : sourceTracks) {
if (track.getFlavor().getType().equals(editedTrackFlavor.getType())) {
mp.addDerived(editedTrack, track);
mpAdded = true;
break;
}
}
if (!mpAdded) {
mp.add(editedTrack);
}
} catch (MediaPackageException ex) {
throw new WorkflowOperationException("Failed to get information about the edited track(s)", ex);
} catch (NotFoundException | IOException | IllegalArgumentException ex) {
throw new WorkflowOperationException("Moving edited track to work location failed.", ex);
} catch (Exception ex) {
throw new WorkflowOperationException(ex);
}
}
logger.info("VideoEdit workflow {} finished", workflowInstance.getId());
return createResult(mp, Action.CONTINUE);
}
use of org.opencastproject.mediapackage.Track in project opencast by opencast.
the class WaveformServiceImplTest method readTrackFromResource.
private static Track readTrackFromResource(String resourceName) throws IOException, MediaPackageException {
BufferedReader reader = null;
try {
reader = new BufferedReader(new InputStreamReader(WaveformServiceImplTest.class.getResourceAsStream(resourceName)));
String line = reader.readLine();
StringBuilder trackBuilder = new StringBuilder();
while (line != null) {
trackBuilder.append(line);
line = reader.readLine();
}
return (Track) MediaPackageElementParser.getFromXml(trackBuilder.toString());
} finally {
IoSupport.closeQuietly(reader);
}
}
use of org.opencastproject.mediapackage.Track in project opencast by opencast.
the class AudioVisualElementSelector method select.
/**
* Returns a track or a number of tracks from the media package that together contain audio and video. If no such
* combination can be found, e. g. there is no audio or video at all, an empty array is returned.
*
* @see org.opencastproject.mediapackage.selector.AbstractMediaPackageElementSelector#select(org.opencastproject.mediapackage.MediaPackage, boolean)
*/
@Override
public Collection<Track> select(MediaPackage mediaPackage, boolean withTagsAndFlavors) {
Collection<Track> candidates = super.select(mediaPackage, withTagsAndFlavors);
Set<Track> result = new HashSet<Track>();
boolean foundAudio = false;
boolean foundVideo = false;
// Try to look for the perfect match: a track containing audio and video
for (Track t : candidates) {
if (audioFlavor == null && videoFlavor == null) {
foundAudio |= t.hasAudio();
foundVideo |= t.hasVideo();
result.add(t);
} else {
if (audioFlavor != null && t.hasAudio() && audioFlavor.matches(t.getFlavor()) && !(videoFlavor == null && t.hasVideo())) {
foundAudio = true;
audioTrack = t;
result.add(t);
}
if (videoFlavor != null && t.hasVideo() && videoFlavor.matches(t.getFlavor()) && !(audioFlavor == null && t.hasAudio())) {
foundVideo = true;
videoTrack = t;
result.add(t);
}
}
if ((foundAudio || audioFlavor == null) && (foundVideo || videoFlavor == null))
break;
}
if ((!foundAudio && requireAudio) || (!foundVideo && requireVideo))
result.clear();
// We were lucky, a combination was found!
return result;
}
Aggregations