use of org.w3c.dom.smil.SMILElement in project Signal-Android by WhisperSystems.
the class SmilUtil method createSmilDocument.
private static SMILDocument createSmilDocument(PduBody body) {
Log.w(TAG, "Creating SMIL document from PduBody.");
SMILDocument document = new SmilDocumentImpl();
SMILElement smilElement = (SMILElement) document.createElement("smil");
document.appendChild(smilElement);
SMILElement headElement = (SMILElement) document.createElement("head");
smilElement.appendChild(headElement);
SMILLayoutElement layoutElement = (SMILLayoutElement) document.createElement("layout");
headElement.appendChild(layoutElement);
SMILRootLayoutElement rootLayoutElement = (SMILRootLayoutElement) document.createElement("root-layout");
rootLayoutElement.setWidth(ROOT_WIDTH);
rootLayoutElement.setHeight(ROOT_HEIGHT);
layoutElement.appendChild(rootLayoutElement);
SMILElement bodyElement = (SMILElement) document.createElement("body");
smilElement.appendChild(bodyElement);
SMILParElement par = (SMILParElement) document.createElement("par");
bodyElement.appendChild(par);
for (int i = 0; i < body.getPartsNum(); i++) {
PduPart part = body.getPart(i);
SMILRegionElement regionElement = getRegion(document, part);
SMILMediaElement mediaElement = getMediaElement(document, part);
if (regionElement != null) {
((SMILRegionMediaElement) mediaElement).setRegion(regionElement);
layoutElement.appendChild(regionElement);
}
par.appendChild(mediaElement);
}
return document;
}
use of org.w3c.dom.smil.SMILElement in project opencast by opencast.
the class PartialImportWorkflowOperationHandler method concat.
private WorkflowOperationResult concat(MediaPackage src, WorkflowOperationInstance operation, List<MediaPackageElement> elementsToClean) throws EncoderException, IOException, NotFoundException, MediaPackageException, WorkflowOperationException, ServiceRegistryException {
final MediaPackage mediaPackage = (MediaPackage) src.clone();
final Long operationId = operation.getId();
//
// read config options
final Opt<String> presenterFlavor = getOptConfig(operation, SOURCE_PRESENTER_FLAVOR);
final Opt<String> presentationFlavor = getOptConfig(operation, SOURCE_PRESENTATION_FLAVOR);
final String smilFlavor = getConfig(operation, SOURCE_SMIL_FLAVOR);
final String concatEncodingProfile = getConfig(operation, CONCAT_ENCODING_PROFILE);
final Opt<String> concatOutputFramerate = getOptConfig(operation, CONCAT_OUTPUT_FRAMERATE);
final String trimEncodingProfile = getConfig(operation, TRIM_ENCODING_PROFILE);
final MediaPackageElementFlavor targetPresenterFlavor = parseTargetFlavor(getConfig(operation, TARGET_PRESENTER_FLAVOR), "presenter");
final MediaPackageElementFlavor targetPresentationFlavor = parseTargetFlavor(getConfig(operation, TARGET_PRESENTATION_FLAVOR), "presentation");
final Opt<EncodingProfile> forceProfile = getForceEncodingProfile(operation);
final boolean forceEncoding = BooleanUtils.toBoolean(getOptConfig(operation, FORCE_ENCODING).getOr("false"));
final boolean forceDivisible = BooleanUtils.toBoolean(getOptConfig(operation, ENFORCE_DIVISIBLE_BY_TWO).getOr("false"));
final List<String> requiredExtensions = getRequiredExtensions(operation);
// Skip the worklow if no presenter and presentation flavor has been configured
if (presenterFlavor.isNone() && presentationFlavor.isNone()) {
logger.warn("No presenter and presentation flavor has been set.");
return createResult(mediaPackage, Action.SKIP);
}
final EncodingProfile concatProfile = composerService.getProfile(concatEncodingProfile);
if (concatProfile == null) {
throw new WorkflowOperationException("Concat encoding profile '" + concatEncodingProfile + "' was not found");
}
float outputFramerate = -1.0f;
if (concatOutputFramerate.isSome()) {
if (NumberUtils.isNumber(concatOutputFramerate.get())) {
logger.info("Using concat output framerate");
outputFramerate = NumberUtils.toFloat(concatOutputFramerate.get());
} else {
throw new WorkflowOperationException("Unable to parse concat output frame rate!");
}
}
final EncodingProfile trimProfile = composerService.getProfile(trimEncodingProfile);
if (trimProfile == null) {
throw new WorkflowOperationException("Trim encoding profile '" + trimEncodingProfile + "' was not found");
}
//
// get tracks
final TrackSelector presenterTrackSelector = mkTrackSelector(presenterFlavor);
final TrackSelector presentationTrackSelector = mkTrackSelector(presentationFlavor);
final List<Track> originalTracks = new ArrayList<Track>();
final List<Track> presenterTracks = new ArrayList<Track>();
final List<Track> presentationTracks = new ArrayList<Track>();
// Collecting presenter tracks
for (Track t : presenterTrackSelector.select(mediaPackage, false)) {
logger.info("Found partial presenter track {}", t);
originalTracks.add(t);
presenterTracks.add(t);
}
// Collecting presentation tracks
for (Track t : presentationTrackSelector.select(mediaPackage, false)) {
logger.info("Found partial presentation track {}", t);
originalTracks.add(t);
presentationTracks.add(t);
}
// flavor_type -> job
final Map<String, Job> jobs = new HashMap<String, Job>();
// get SMIL catalog
final SMILDocument smilDocument = getSmilDocumentFromMediaPackage(mediaPackage, smilFlavor);
final SMILParElement parallel = (SMILParElement) smilDocument.getBody().getChildNodes().item(0);
final NodeList sequences = parallel.getTimeChildren();
final float trackDurationInSeconds = parallel.getDur();
final long trackDurationInMs = Math.round(trackDurationInSeconds * 1000f);
for (int i = 0; i < sequences.getLength(); i++) {
final SMILElement item = (SMILElement) sequences.item(i);
for (final String mediaType : new String[] { NODE_TYPE_AUDIO, NODE_TYPE_VIDEO }) {
final List<Track> tracks = new ArrayList<Track>();
final VCell<String> sourceType = VCell.cell(EMPTY_VALUE);
final long position = processChildren(0, tracks, item.getChildNodes(), originalTracks, sourceType, mediaType, elementsToClean, operationId);
if (tracks.isEmpty()) {
logger.debug("The tracks list was empty.");
continue;
}
final Track lastTrack = tracks.get(tracks.size() - 1);
if (position < trackDurationInMs) {
final double extendingTime = (trackDurationInMs - position) / 1000d;
if (extendingTime > 0) {
if (!lastTrack.hasVideo()) {
logger.info("Extending {} audio track end by {} seconds with silent audio", sourceType.get(), extendingTime);
tracks.add(getSilentAudio(extendingTime, elementsToClean, operationId));
} else {
logger.info("Extending {} track end with last image frame by {} seconds", sourceType.get(), extendingTime);
Attachment tempLastImageFrame = extractLastImageFrame(lastTrack, elementsToClean);
tracks.add(createVideoFromImage(tempLastImageFrame, extendingTime, elementsToClean));
}
}
}
if (tracks.size() < 2) {
logger.debug("There were less than 2 tracks, copying track...");
if (sourceType.get().startsWith(PRESENTER_KEY)) {
createCopyOfTrack(mediaPackage, tracks.get(0), targetPresenterFlavor);
} else if (sourceType.get().startsWith(PRESENTATION_KEY)) {
createCopyOfTrack(mediaPackage, tracks.get(0), targetPresentationFlavor);
} else {
logger.warn("Can't handle unkown source type '{}' for unprocessed track", sourceType.get());
}
continue;
}
for (final Track t : tracks) {
if (!t.hasVideo() && !t.hasAudio()) {
logger.error("No audio or video stream available in the track with flavor {}! {}", t.getFlavor(), t);
throw new WorkflowOperationException("No audio or video stream available in the track " + t.toString());
}
}
if (sourceType.get().startsWith(PRESENTER_KEY)) {
logger.info("Concatenating {} track", PRESENTER_KEY);
jobs.put(sourceType.get(), startConcatJob(concatProfile, tracks, outputFramerate, forceDivisible));
} else if (sourceType.get().startsWith(PRESENTATION_KEY)) {
logger.info("Concatenating {} track", PRESENTATION_KEY);
jobs.put(sourceType.get(), startConcatJob(concatProfile, tracks, outputFramerate, forceDivisible));
} else {
logger.warn("Can't handle unknown source type '{}'!", sourceType.get());
}
}
}
// Wait for the jobs to return
if (jobs.size() > 0) {
if (!JobUtil.waitForJobs(serviceRegistry, jobs.values()).isSuccess()) {
throw new WorkflowOperationException("One of the concat jobs did not complete successfully");
}
} else {
logger.info("No concatenating needed for presenter and presentation tracks, took partial source elements");
}
// All the jobs have passed, let's update the media package
long queueTime = 0L;
MediaPackageElementFlavor adjustedTargetPresenterFlavor = targetPresenterFlavor;
MediaPackageElementFlavor adjustedTargetPresentationFlavor = targetPresentationFlavor;
for (final Entry<String, Job> job : jobs.entrySet()) {
final Opt<Job> concatJob = JobUtil.update(serviceRegistry, job.getValue());
if (concatJob.isSome()) {
final String concatPayload = concatJob.get().getPayload();
if (concatPayload != null) {
final Track concatTrack;
try {
concatTrack = (Track) MediaPackageElementParser.getFromXml(concatPayload);
} catch (MediaPackageException e) {
throw new WorkflowOperationException(e);
}
final String fileName;
// Adjust the target flavor.
if (job.getKey().startsWith(PRESENTER_KEY)) {
if (!concatTrack.hasVideo()) {
fileName = PRESENTER_KEY.concat(FLAVOR_AUDIO_SUFFIX);
adjustedTargetPresenterFlavor = deriveAudioFlavor(targetPresenterFlavor);
} else {
fileName = PRESENTER_KEY;
adjustedTargetPresenterFlavor = targetPresenterFlavor;
}
concatTrack.setFlavor(adjustedTargetPresenterFlavor);
} else if (job.getKey().startsWith(PRESENTATION_KEY)) {
if (!concatTrack.hasVideo()) {
fileName = PRESENTATION_KEY.concat(FLAVOR_AUDIO_SUFFIX);
adjustedTargetPresentationFlavor = deriveAudioFlavor(targetPresentationFlavor);
} else {
fileName = PRESENTATION_KEY;
adjustedTargetPresentationFlavor = targetPresentationFlavor;
}
concatTrack.setFlavor(adjustedTargetPresentationFlavor);
} else {
fileName = UNKNOWN_KEY;
}
concatTrack.setURI(workspace.moveTo(concatTrack.getURI(), mediaPackage.getIdentifier().toString(), concatTrack.getIdentifier(), fileName + "." + FilenameUtils.getExtension(concatTrack.getURI().toString())));
logger.info("Concatenated track {} got flavor '{}'", concatTrack, concatTrack.getFlavor());
mediaPackage.add(concatTrack);
queueTime += concatJob.get().getQueueTime();
} else {
// If there is no payload, then the item has not been distributed.
logger.warn("Concat job {} does not contain a payload", concatJob);
}
} else {
logger.warn("Concat job {} could not be updated since it cannot be found", job.getValue());
}
}
// Trim presenter and presentation source track if longer than the duration from the SMIL catalog
queueTime += checkForTrimming(mediaPackage, trimProfile, targetPresentationFlavor, trackDurationInSeconds, elementsToClean);
queueTime += checkForTrimming(mediaPackage, trimProfile, deriveAudioFlavor(targetPresentationFlavor), trackDurationInSeconds, elementsToClean);
queueTime += checkForTrimming(mediaPackage, trimProfile, targetPresenterFlavor, trackDurationInSeconds, elementsToClean);
queueTime += checkForTrimming(mediaPackage, trimProfile, deriveAudioFlavor(targetPresenterFlavor), trackDurationInSeconds, elementsToClean);
adjustAudioTrackTargetFlavor(mediaPackage, targetPresenterFlavor);
adjustAudioTrackTargetFlavor(mediaPackage, targetPresentationFlavor);
queueTime += checkForMuxing(mediaPackage, targetPresenterFlavor, targetPresentationFlavor, false, elementsToClean);
queueTime += checkForEncodeToStandard(mediaPackage, forceEncoding, forceProfile, requiredExtensions, targetPresenterFlavor, targetPresentationFlavor, elementsToClean);
final WorkflowOperationResult result = createResult(mediaPackage, Action.CONTINUE, queueTime);
logger.debug("Partial import operation completed");
return result;
}
use of org.w3c.dom.smil.SMILElement in project android-aosp-mms by slvn.
the class SlideshowActivity method isMMSConformance.
/**
* @return whether the Smil has MMS conformance layout.
* Refer to MMS Conformance Document OMA-MMS-CONF-v1_2-20050301-A
*/
private static final boolean isMMSConformance(SMILDocument smilDoc) {
SMILElement head = smilDoc.getHead();
if (head == null) {
// No 'head' element
return false;
}
NodeList children = head.getChildNodes();
if (children == null || children.getLength() != 1) {
// The 'head' element should have only one child.
return false;
}
Node layout = children.item(0);
if (layout == null || !"layout".equals(layout.getNodeName())) {
// The child is not layout element
return false;
}
NodeList layoutChildren = layout.getChildNodes();
if (layoutChildren == null) {
// The 'layout' element has no child.
return false;
}
int num = layoutChildren.getLength();
if (num <= 0) {
// The 'layout' element has no child.
return false;
}
for (int i = 0; i < num; i++) {
Node layoutChild = layoutChildren.item(i);
if (layoutChild == null) {
// The 'layout' child is null.
return false;
}
String name = layoutChild.getNodeName();
if ("root-layout".equals(name)) {
continue;
} else if ("region".equals(name)) {
NamedNodeMap map = layoutChild.getAttributes();
for (int j = 0; j < map.getLength(); j++) {
Node node = map.item(j);
if (node == null) {
return false;
}
String attrName = node.getNodeName();
// The attr should be one of left, top, height, width, fit and id
if ("left".equals(attrName) || "top".equals(attrName) || "height".equals(attrName) || "width".equals(attrName) || "fit".equals(attrName)) {
continue;
} else if ("id".equals(attrName)) {
String value;
if (node instanceof AttrImpl) {
value = ((AttrImpl) node).getValue();
} else {
return false;
}
if ("Text".equals(value) || "Image".equals(value)) {
continue;
} else {
// The id attr is not 'Text' or 'Image'
return false;
}
} else {
return false;
}
}
} else {
// The 'layout' element has the child other than 'root-layout' or 'region'
return false;
}
}
return true;
}
use of org.w3c.dom.smil.SMILElement in project android-aosp-mms by slvn.
the class SmilHelper method createSmilDocument.
private static SMILDocument createSmilDocument(SlideshowModel slideshow) {
if (Config.LOGV) {
Log.v(TAG, "Creating SMIL document from SlideshowModel.");
}
SMILDocument document = new SmilDocumentImpl();
// Create SMIL and append it to document
SMILElement smilElement = (SMILElement) document.createElement("smil");
document.appendChild(smilElement);
// Create HEAD and append it to SMIL
SMILElement headElement = (SMILElement) document.createElement("head");
smilElement.appendChild(headElement);
// Create LAYOUT and append it to HEAD
SMILLayoutElement layoutElement = (SMILLayoutElement) document.createElement("layout");
headElement.appendChild(layoutElement);
// Create ROOT-LAYOUT and append it to LAYOUT
SMILRootLayoutElement rootLayoutElement = (SMILRootLayoutElement) document.createElement("root-layout");
LayoutModel layouts = slideshow.getLayout();
rootLayoutElement.setWidth(layouts.getLayoutWidth());
rootLayoutElement.setHeight(layouts.getLayoutHeight());
String bgColor = layouts.getBackgroundColor();
if (!TextUtils.isEmpty(bgColor)) {
rootLayoutElement.setBackgroundColor(bgColor);
}
layoutElement.appendChild(rootLayoutElement);
// Create REGIONs and append them to LAYOUT
ArrayList<RegionModel> regions = layouts.getRegions();
ArrayList<SMILRegionElement> smilRegions = new ArrayList<SMILRegionElement>();
for (RegionModel r : regions) {
SMILRegionElement smilRegion = (SMILRegionElement) document.createElement("region");
smilRegion.setId(r.getRegionId());
smilRegion.setLeft(r.getLeft());
smilRegion.setTop(r.getTop());
smilRegion.setWidth(r.getWidth());
smilRegion.setHeight(r.getHeight());
smilRegion.setFit(r.getFit());
smilRegions.add(smilRegion);
}
// Create BODY and append it to the document.
SMILElement bodyElement = (SMILElement) document.createElement("body");
smilElement.appendChild(bodyElement);
for (SlideModel slide : slideshow) {
boolean txtRegionPresentInLayout = false;
boolean imgRegionPresentInLayout = false;
// Create PAR element.
SMILParElement par = addPar(document);
par.setDur(slide.getDuration() / 1000f);
addParElementEventListeners((EventTarget) par, slide);
// Add all media elements.
for (MediaModel media : slide) {
SMILMediaElement sme = null;
String src = media.getSrc();
if (media instanceof TextModel) {
TextModel text = (TextModel) media;
if (TextUtils.isEmpty(text.getText())) {
if (LOCAL_LOGV) {
Log.v(TAG, "Empty text part ignored: " + text.getSrc());
}
continue;
}
sme = SmilHelper.createMediaElement(SmilHelper.ELEMENT_TAG_TEXT, document, src);
txtRegionPresentInLayout = setRegion((SMILRegionMediaElement) sme, smilRegions, layoutElement, LayoutModel.TEXT_REGION_ID, txtRegionPresentInLayout);
} else if (media instanceof ImageModel) {
sme = SmilHelper.createMediaElement(SmilHelper.ELEMENT_TAG_IMAGE, document, src);
imgRegionPresentInLayout = setRegion((SMILRegionMediaElement) sme, smilRegions, layoutElement, LayoutModel.IMAGE_REGION_ID, imgRegionPresentInLayout);
} else if (media instanceof VideoModel) {
sme = SmilHelper.createMediaElement(SmilHelper.ELEMENT_TAG_VIDEO, document, src);
imgRegionPresentInLayout = setRegion((SMILRegionMediaElement) sme, smilRegions, layoutElement, LayoutModel.IMAGE_REGION_ID, imgRegionPresentInLayout);
} else if (media instanceof AudioModel) {
sme = SmilHelper.createMediaElement(SmilHelper.ELEMENT_TAG_AUDIO, document, src);
} else {
Log.w(TAG, "Unsupport media: " + media);
continue;
}
// Set timing information.
int begin = media.getBegin();
if (begin != 0) {
sme.setAttribute("begin", String.valueOf(begin / 1000));
}
int duration = media.getDuration();
if (duration != 0) {
sme.setDur((float) duration / 1000);
}
par.appendChild(sme);
addMediaElementEventListeners((EventTarget) sme, media);
}
}
if (LOCAL_LOGV) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
SmilXmlSerializer.serialize(document, out);
Log.v(TAG, out.toString());
}
return document;
}
use of org.w3c.dom.smil.SMILElement in project android-aosp-mms by slvn.
the class SmilDocumentImpl method getDocumentElement.
@Override
public SMILElement getDocumentElement() {
Node rootElement = getFirstChild();
if (rootElement == null || !(rootElement instanceof SMILElement)) {
// The root doesn't exist. Create a new one.
rootElement = createElement("smil");
appendChild(rootElement);
}
return (SMILElement) rootElement;
}
Aggregations