use of org.opencastproject.mediapackage.Catalog in project opencast by opencast.
the class SolrIndexManager method createEpisodeInputDocument.
/**
* Creates a solr input document for the episode metadata of the media package.
*
* @param mediaPackage
* the media package
* @param acl
* the access control list for this mediapackage
* @return an input document ready to be posted to solr
* @throws MediaPackageException
* if serialization of the media package fails
*/
private SolrInputDocument createEpisodeInputDocument(MediaPackage mediaPackage, AccessControlList acl) throws MediaPackageException, IOException {
SolrInputDocument doc = new SolrInputDocument();
String mediaPackageId = mediaPackage.getIdentifier().toString();
// Fill the input document
Schema.setId(doc, mediaPackageId);
// /
// OC specific fields
Schema.setOcMediatype(doc, SearchResultItemType.AudioVisual.toString());
Schema.setOrganization(doc, securityService.getOrganization().getId());
Schema.setOcMediapackage(doc, MediaPackageParser.getAsXml(mediaPackage));
Schema.setOcElementtags(doc, tags(mediaPackage));
Schema.setOcElementflavors(doc, flavors(mediaPackage));
// Add cover
Attachment[] cover = mediaPackage.getAttachments(MediaPackageElements.MEDIAPACKAGE_COVER_FLAVOR);
if (cover != null && cover.length > 0) {
Schema.setOcCover(doc, cover[0].getURI().toString());
}
// naive approach. works as long as only setters, not adders are available in the schema
for (StaticMetadata md : getMetadata(mdServices, mediaPackage)) addEpisodeMetadata(doc, md);
// /
// Add mpeg7
logger.debug("Looking for mpeg-7 catalogs containing segment texts");
Catalog[] mpeg7Catalogs = mediaPackage.getCatalogs(MediaPackageElements.TEXTS);
if (mpeg7Catalogs.length == 0) {
logger.debug("No text catalogs found, trying segments only");
mpeg7Catalogs = mediaPackage.getCatalogs(MediaPackageElements.SEGMENTS);
}
// TODO: merge the segments from each mpeg7 if there is more than one mpeg7 catalog
if (mpeg7Catalogs.length > 0) {
try {
Mpeg7Catalog mpeg7Catalog = loadMpeg7Catalog(mpeg7Catalogs[0]);
addMpeg7Metadata(doc, mediaPackage, mpeg7Catalog);
} catch (IOException e) {
logger.error("Error loading mpeg7 catalog. Skipping catalog: {}", e.getMessage());
}
} else {
logger.debug("No segmentation catalog found");
}
// /
// Add authorization
setAuthorization(doc, securityService, acl);
return doc;
}
use of org.opencastproject.mediapackage.Catalog in project opencast by opencast.
the class SegmentPreviewsWorkflowOperationHandler method createPreviews.
/**
* Encode tracks from MediaPackage using profiles stored in properties and updates current MediaPackage.
*
* @param mediaPackage
* @param properties
* @return the operation result containing the updated mediapackage
* @throws EncoderException
* @throws ExecutionException
* @throws InterruptedException
* @throws IOException
* @throws NotFoundException
* @throws WorkflowOperationException
*/
private WorkflowOperationResult createPreviews(final MediaPackage mediaPackage, WorkflowOperationInstance operation) throws EncoderException, InterruptedException, ExecutionException, NotFoundException, MediaPackageException, IOException, WorkflowOperationException {
long totalTimeInQueue = 0;
// Read the configuration properties
String sourceVideoFlavor = StringUtils.trimToNull(operation.getConfiguration("source-flavor"));
String sourceTags = StringUtils.trimToNull(operation.getConfiguration("source-tags"));
String targetImageTags = StringUtils.trimToNull(operation.getConfiguration("target-tags"));
String targetImageFlavor = StringUtils.trimToNull(operation.getConfiguration("target-flavor"));
String encodingProfileName = StringUtils.trimToNull(operation.getConfiguration("encoding-profile"));
String referenceFlavor = StringUtils.trimToNull(operation.getConfiguration("reference-flavor"));
String referenceTags = StringUtils.trimToNull(operation.getConfiguration("reference-tags"));
// Find the encoding profile
EncodingProfile profile = composerService.getProfile(encodingProfileName);
if (profile == null)
throw new IllegalStateException("Encoding profile '" + encodingProfileName + "' was not found");
List<String> sourceTagSet = asList(sourceTags);
// Select the tracks based on the tags and flavors
Set<Track> videoTrackSet = new HashSet<>();
for (Track track : mediaPackage.getTracksByTags(sourceTagSet)) {
if (sourceVideoFlavor == null || (track.getFlavor() != null && sourceVideoFlavor.equals(track.getFlavor().toString()))) {
if (!track.hasVideo())
continue;
videoTrackSet.add(track);
}
}
if (videoTrackSet.size() == 0) {
logger.debug("Mediapackage {} has no suitable tracks to extract images based on tags {} and flavor {}", mediaPackage, sourceTags, sourceVideoFlavor);
return createResult(mediaPackage, Action.CONTINUE);
} else {
// Determine the tagset for the reference
List<String> referenceTagSet = asList(referenceTags);
// Determine the reference master
for (Track t : videoTrackSet) {
// Try to load the segments catalog
MediaPackageReference trackReference = new MediaPackageReferenceImpl(t);
Catalog[] segmentCatalogs = mediaPackage.getCatalogs(MediaPackageElements.SEGMENTS, trackReference);
Mpeg7Catalog mpeg7 = null;
if (segmentCatalogs.length > 0) {
mpeg7 = loadMpeg7Catalog(segmentCatalogs[0]);
if (segmentCatalogs.length > 1)
logger.warn("More than one segments catalog found for track {}. Resuming with the first one ({})", t, mpeg7);
} else {
logger.debug("No segments catalog found for track {}", t);
continue;
}
// Check the catalog's consistency
if (mpeg7.videoContent() == null || mpeg7.videoContent().next() == null) {
logger.info("Segments catalog {} contains no video content", mpeg7);
continue;
}
Video videoContent = mpeg7.videoContent().next();
TemporalDecomposition<? extends Segment> decomposition = videoContent.getTemporalDecomposition();
// Are there any segments?
if (decomposition == null || !decomposition.hasSegments()) {
logger.info("Segments catalog {} contains no video content", mpeg7);
continue;
}
// Is a derived track with the configured reference flavor available?
MediaPackageElement referenceMaster = getReferenceMaster(mediaPackage, t, referenceFlavor, referenceTagSet);
// Create the preview images according to the mpeg7 segments
if (t.hasVideo() && mpeg7 != null) {
Iterator<? extends Segment> segmentIterator = decomposition.segments();
List<MediaTimePoint> timePointList = new LinkedList<>();
while (segmentIterator.hasNext()) {
Segment segment = segmentIterator.next();
MediaTimePoint tp = segment.getMediaTime().getMediaTimePoint();
timePointList.add(tp);
}
// convert to time array
double[] timeArray = new double[timePointList.size()];
for (int i = 0; i < timePointList.size(); i++) timeArray[i] = (double) timePointList.get(i).getTimeInMilliseconds() / 1000;
Job job = composerService.image(t, profile.getIdentifier(), timeArray);
if (!waitForStatus(job).isSuccess()) {
throw new WorkflowOperationException("Extracting preview image from " + t + " failed");
}
// Get the latest copy
try {
job = serviceRegistry.getJob(job.getId());
} catch (ServiceRegistryException e) {
throw new WorkflowOperationException(e);
}
// add this receipt's queue time to the total
totalTimeInQueue += job.getQueueTime();
List<? extends MediaPackageElement> composedImages = MediaPackageElementParser.getArrayFromXml(job.getPayload());
Iterator<MediaTimePoint> it = timePointList.iterator();
for (MediaPackageElement element : composedImages) {
Attachment composedImage = (Attachment) element;
if (composedImage == null)
throw new IllegalStateException("Unable to compose image");
// Add the flavor, either from the operation configuration or from the composer
if (targetImageFlavor != null) {
composedImage.setFlavor(MediaPackageElementFlavor.parseFlavor(targetImageFlavor));
logger.debug("Preview image has flavor '{}'", composedImage.getFlavor());
}
// Set the mimetype
if (profile.getMimeType() != null)
composedImage.setMimeType(MimeTypes.parseMimeType(profile.getMimeType()));
// Add tags
for (String tag : asList(targetImageTags)) {
logger.trace("Tagging image with '{}'", tag);
composedImage.addTag(tag);
}
// Refer to the original track including a timestamp
MediaPackageReferenceImpl ref = new MediaPackageReferenceImpl(referenceMaster);
ref.setProperty("time", it.next().toString());
composedImage.setReference(ref);
// store new image in the mediaPackage
mediaPackage.add(composedImage);
String fileName = getFileNameFromElements(t, composedImage);
composedImage.setURI(workspace.moveTo(composedImage.getURI(), mediaPackage.getIdentifier().toString(), composedImage.getIdentifier(), fileName));
}
}
}
}
return createResult(mediaPackage, Action.CONTINUE, totalTimeInQueue);
}
use of org.opencastproject.mediapackage.Catalog in project opencast by opencast.
the class SeriesUpdatedEventHandler method handleEvent.
public void handleEvent(final SeriesItem seriesItem) {
// A series or its ACL has been updated. Find any mediapackages with that series, and update them.
logger.debug("Handling {}", seriesItem);
String seriesId = seriesItem.getSeriesId();
// We must be an administrative user to make this query
final User prevUser = securityService.getUser();
final Organization prevOrg = securityService.getOrganization();
try {
securityService.setUser(SecurityUtil.createSystemUser(systemAccount, prevOrg));
SearchQuery q = new SearchQuery().withSeriesId(seriesId);
SearchResult result = searchService.getForAdministrativeRead(q);
for (SearchResultItem item : result.getItems()) {
MediaPackage mp = item.getMediaPackage();
Organization org = organizationDirectoryService.getOrganization(item.getOrganization());
securityService.setOrganization(org);
// to the distribution channels as well
if (SeriesItem.Type.UpdateAcl.equals(seriesItem.getType())) {
// Build a new XACML file for this mediapackage
Attachment fileRepoCopy = authorizationService.setAcl(mp, AclScope.Series, seriesItem.getAcl()).getB();
// Distribute the updated XACML file
Job distributionJob = distributionService.distribute(CHANNEL_ID, mp, fileRepoCopy.getIdentifier());
JobBarrier barrier = new JobBarrier(null, serviceRegistry, distributionJob);
Result jobResult = barrier.waitForJobs();
if (jobResult.getStatus().get(distributionJob).equals(FINISHED)) {
mp.remove(fileRepoCopy);
mp.add(getFromXml(serviceRegistry.getJob(distributionJob.getId()).getPayload()));
} else {
logger.error("Unable to distribute XACML {}", fileRepoCopy.getIdentifier());
continue;
}
}
// Update the series dublin core
if (SeriesItem.Type.UpdateCatalog.equals(seriesItem.getType())) {
DublinCoreCatalog seriesDublinCore = seriesItem.getMetadata();
mp.setSeriesTitle(seriesDublinCore.getFirst(DublinCore.PROPERTY_TITLE));
// Update the series dublin core
Catalog[] seriesCatalogs = mp.getCatalogs(MediaPackageElements.SERIES);
if (seriesCatalogs.length == 1) {
Catalog c = seriesCatalogs[0];
String filename = FilenameUtils.getName(c.getURI().toString());
URI uri = workspace.put(mp.getIdentifier().toString(), c.getIdentifier(), filename, dublinCoreService.serialize(seriesDublinCore));
c.setURI(uri);
// setting the URI to a new source so the checksum will most like be invalid
c.setChecksum(null);
// Distribute the updated series dc
Job distributionJob = distributionService.distribute(CHANNEL_ID, mp, c.getIdentifier());
JobBarrier barrier = new JobBarrier(null, serviceRegistry, distributionJob);
Result jobResult = barrier.waitForJobs();
if (jobResult.getStatus().get(distributionJob).equals(FINISHED)) {
mp.remove(c);
mp.add(getFromXml(serviceRegistry.getJob(distributionJob.getId()).getPayload()));
} else {
logger.error("Unable to distribute series catalog {}", c.getIdentifier());
continue;
}
}
}
// Remove the series catalog and isPartOf from episode catalog
if (SeriesItem.Type.Delete.equals(seriesItem.getType())) {
mp.setSeries(null);
mp.setSeriesTitle(null);
boolean retractSeriesCatalog = retractSeriesCatalog(mp);
boolean updateEpisodeCatalog = updateEpisodeCatalog(mp);
if (!retractSeriesCatalog || !updateEpisodeCatalog)
continue;
}
// Update the search index with the modified mediapackage
Job searchJob = searchService.add(mp);
JobBarrier barrier = new JobBarrier(null, serviceRegistry, searchJob);
barrier.waitForJobs();
}
} catch (SearchException e) {
logger.warn("Unable to find mediapackages in search: ", e.getMessage());
} catch (UnauthorizedException e) {
logger.warn(e.getMessage());
} catch (MediaPackageException e) {
logger.warn(e.getMessage());
} catch (ServiceRegistryException e) {
logger.warn(e.getMessage());
} catch (NotFoundException e) {
logger.warn(e.getMessage());
} catch (IOException e) {
logger.warn(e.getMessage());
} catch (DistributionException e) {
logger.warn(e.getMessage());
} finally {
securityService.setOrganization(prevOrg);
securityService.setUser(prevUser);
}
}
use of org.opencastproject.mediapackage.Catalog in project opencast by opencast.
the class SeriesUpdatedEventHandler method retractSeriesCatalog.
private boolean retractSeriesCatalog(MediaPackage mp) throws DistributionException {
// Retract the series catalog
for (Catalog c : mp.getCatalogs(MediaPackageElements.SERIES)) {
Job retractJob = distributionService.retract(CHANNEL_ID, mp, c.getIdentifier());
JobBarrier barrier = new JobBarrier(null, serviceRegistry, retractJob);
Result jobResult = barrier.waitForJobs();
if (jobResult.getStatus().get(retractJob).equals(FINISHED)) {
mp.remove(c);
} else {
logger.error("Unable to retract series catalog {}", c.getIdentifier());
return false;
}
}
return true;
}
use of org.opencastproject.mediapackage.Catalog in project opencast by opencast.
the class OaiPmhUpdatedEventHandlerTest method testHandleEvent.
/**
* Tests "normal" behavior, where the media package contains at least one element with the given flavor and tags
*/
@Test
public void testHandleEvent() throws Exception {
Catalog episodeCatalog = CatalogImpl.newInstance();
episodeCatalog.setURI(URI.create("/episode.xml"));
episodeCatalog.setFlavor(MediaPackageElementFlavor.parseFlavor("dublincore/episode"));
episodeCatalog.addTag("archive");
MediaPackage updatedMp = createMediaPackage(episodeCatalog);
// these are the interactions we expect with the security service
mockSecurityService();
// these are the interactions we expect for the OAI-PMH database
mockOaiPmhDatabase();
Capture<MediaPackage> mpCapture = Capture.newInstance();
Capture<String> repositoryCapture = Capture.newInstance();
Capture<Set<String>> flavorsCapture = Capture.newInstance();
Capture<Set> tagsCapture = Capture.newInstance();
expect(oaiPmhPublicationService.updateMetadata(capture(mpCapture), capture(repositoryCapture), capture(flavorsCapture), capture(tagsCapture), anyBoolean())).andAnswer(() -> mock(Job.class)).times(1);
replayAll();
cut.handleEvent(createSnapshot(updatedMp));
assertEquals(updatedMp.getIdentifier().compact(), mpCapture.getValue().getIdentifier().compact());
assertEquals(OAIPMH_REPOSITORY, repositoryCapture.getValue());
Assert.assertNotNull(flavorsCapture.getValue());
Assert.assertTrue(flavorsCapture.getValue().contains("dublincore/*"));
Assert.assertTrue(flavorsCapture.getValue().contains("security/*"));
Assert.assertTrue(tagsCapture.getValue().contains("archive"));
}
Aggregations