Esempio n. 1
0
  /**
   * A stateless method that returns the RFC-5646 Spoken Language Tag present in the Header
   * Partition of an Audio Essence
   *
   * @param essencesHeaderPartition - a list of payloads corresponding to the Header Partitions of
   *     TrackFiles that are a part of an Audio VirtualTrack
   * @param audioVirtualTrack - the audio virtual track whose spoken language needs to be
   *     ascertained
   * @return string corresponding to the RFC-5646 language tag present in the header partition of
   *     the Audio Essence
   * @throws IOException - any I/O related error is exposed through an IOException
   */
  @Nullable
  public static String getAudioTrackSpokenLanguage(
      VirtualTrack audioVirtualTrack, List<PayloadRecord> essencesHeaderPartition)
      throws IOException {
    IMFErrorLogger imfErrorLogger = new IMFErrorLoggerImpl();
    if (audioVirtualTrack.getSequenceTypeEnum() != Composition.SequenceTypeEnum.MainAudioSequence) {
      throw new IMFException(
          String.format(
              "Virtual track that was passed in is of type %s, spoken language is "
                  + "currently supported for only %s tracks",
              audioVirtualTrack.getSequenceTypeEnum().toString(),
              Composition.SequenceTypeEnum.MainAudioSequence.toString()));
    }
    List<VirtualTrack> virtualTracks = new ArrayList<>();
    virtualTracks.add(audioVirtualTrack);
    imfErrorLogger.addAllErrors(
        checkVirtualTrackAndEssencesHeaderPartitionPayloadRecords(
            virtualTracks, essencesHeaderPartition));
    if (imfErrorLogger.hasFatalErrors()) {
      throw new IMFException(
          String.format(
              "Fatal Errors were detected when trying to verify the Virtual Track and Essence Header Partition payloads %s",
              Utilities.serializeObjectCollectionToString(imfErrorLogger.getErrors())));
    }
    Set<String> audioLanguageSet = new HashSet<>();
    for (PayloadRecord payloadRecord : essencesHeaderPartition) {
      if (payloadRecord.getPayloadAssetType() != PayloadRecord.PayloadAssetType.EssencePartition) {
        throw new IMFException(
            String.format(
                "Payload asset type is %s, expected asset type %s",
                payloadRecord.getPayloadAssetType(),
                PayloadRecord.PayloadAssetType.EssencePartition.toString()),
            imfErrorLogger);
      }
      HeaderPartition headerPartition =
          new HeaderPartition(
              new ByteArrayDataProvider(payloadRecord.getPayload()),
              0L,
              (long) payloadRecord.getPayload().length,
              imfErrorLogger);
      audioLanguageSet.add(headerPartition.getAudioEssenceSpokenLanguage());
    }

    if (audioLanguageSet.size() > 1) {
      throw new IMFException(
          String.format(
              "It seems that RFC-5646 spoken language is not consistent across "
                  + "resources of this Audio Virtual Track, found references to %s languages in the HeaderPartition",
              Utilities.serializeObjectCollectionToString(audioLanguageSet)),
          imfErrorLogger);
    }
    return audioLanguageSet.iterator().next();
  }
Esempio n. 2
0
 private static boolean compareAudioVirtualTrackMaps(
     Map<Set<DOMNodeObjectModel>, ? extends VirtualTrack> map1,
     Map<Set<DOMNodeObjectModel>, ? extends VirtualTrack> map2,
     IMFErrorLogger imfErrorLogger) {
   boolean result = true;
   Iterator refIterator = map1.entrySet().iterator();
   while (refIterator.hasNext()) {
     Map.Entry<Set<DOMNodeObjectModel>, VirtualTrack> entry =
         (Map.Entry<Set<DOMNodeObjectModel>, VirtualTrack>) refIterator.next();
     VirtualTrack refVirtualTrack = entry.getValue();
     VirtualTrack otherVirtualTrack = map2.get(entry.getKey());
     if (otherVirtualTrack
         != null) { // If we identified an audio virtual track with the same essence description we
                    // can compare, else no point comparing hence the default result = true.
       result &= refVirtualTrack.equivalent(otherVirtualTrack);
     }
   }
   return result;
 }
Esempio n. 3
0
  /**
   * A stateless method that determines if 2 or more Composition documents corresponding to the same
   * title can be inferred to represent the same presentation timeline. This method is present to
   * work around current limitations in the IMF eco system wherein CPL's might not be built
   * incrementally to include all the IMF essences that are a part of the same timeline
   *
   * @param referenceCPLPayloadRecord - a payload record corresponding to a Reference Composition
   *     document, perhaps the first composition playlist document that was delivered for a
   *     particular composition.
   * @param cplPayloads - a list of payload records corresponding to each of the Composition
   *     documents that need to be verified for mergeability
   * @return a boolean indicating if the CPLs can be merged or not
   * @throws IOException - any I/O related error is exposed through an IOException
   */
  public static List<ErrorLogger.ErrorObject> isCPLMergeable(
      PayloadRecord referenceCPLPayloadRecord, List<PayloadRecord> cplPayloads) throws IOException {

    IMFErrorLogger imfErrorLogger = new IMFErrorLoggerImpl();
    List<PayloadRecord> cplPayloadRecords = Collections.unmodifiableList(cplPayloads);
    List<Composition> compositions = new ArrayList<>();
    try {
      compositions.add(
          new Composition(new ByteArrayByteRangeProvider(referenceCPLPayloadRecord.getPayload())));
    } catch (IMFException e) {
      imfErrorLogger.addAllErrors(e.getErrors());
    }

    for (PayloadRecord cpl : cplPayloadRecords) {
      try {
        compositions.add(new Composition(new ByteArrayByteRangeProvider(cpl.getPayload())));
      } catch (IMFException e) {
        imfErrorLogger.addAllErrors(e.getErrors());
      }
    }

    if (imfErrorLogger.hasFatalErrors()) {
      return imfErrorLogger.getErrors();
    }

    VirtualTrack referenceVideoVirtualTrack = compositions.get(0).getVideoVirtualTrack();
    UUID referenceCPLUUID = compositions.get(0).getUUID();
    for (int i = 1; i < compositions.size(); i++) {
      if (!referenceVideoVirtualTrack.equivalent(compositions.get(i).getVideoVirtualTrack())) {
        imfErrorLogger.addError(
            IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CPL_ERROR,
            IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
            String.format(
                "CPL Id %s can't be merged with Reference CPL Id %s, since the video virtual tracks do not seem to represent the same timeline.",
                compositions.get(i).getUUID(), referenceCPLUUID));
      }
    }

    /**
     * Perform AudioTrack mergeability checks 1) Identify AudioTracks that are the same language 2)
     * Compare language tracks to see if they represent the same timeline
     */
    Boolean bAudioVirtualTrackMapFail = false;
    List<Map<Set<DOMNodeObjectModel>, ? extends VirtualTrack>> audioVirtualTracksMapList =
        new ArrayList<>();
    for (Composition composition : compositions) {
      try {
        audioVirtualTracksMapList.add(composition.getAudioVirtualTracksMap());
      } catch (IMFException e) {
        bAudioVirtualTrackMapFail = false;
        imfErrorLogger.addAllErrors(e.getErrors());
      }
    }

    if (!bAudioVirtualTrackMapFail) {
      Map<Set<DOMNodeObjectModel>, ? extends VirtualTrack> referenceAudioVirtualTracksMap =
          audioVirtualTracksMapList.get(0);
      for (int i = 1; i < audioVirtualTracksMapList.size(); i++) {
        if (!compareAudioVirtualTrackMaps(
            Collections.unmodifiableMap(referenceAudioVirtualTracksMap),
            Collections.unmodifiableMap(audioVirtualTracksMapList.get(i)),
            imfErrorLogger)) {
          imfErrorLogger.addError(
              IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CPL_ERROR,
              IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
              String.format(
                  "CPL Id %s can't be merged with Reference CPL Id %s, since 2 same language audio tracks do not seem to represent the same timeline.",
                  compositions.get(i).getUUID(), referenceCPLUUID));
        }
      }
    }

    /** Perform MarkerTrack mergeability checks */
    Composition.VirtualTrack referenceMarkerVirtualTrack =
        compositions.get(0).getMarkerVirtualTrack();
    if (referenceMarkerVirtualTrack != null) {
      UUID referenceMarkerCPLUUID = compositions.get(0).getUUID();
      for (int i = 1; i < compositions.size(); i++) {
        if (!referenceVideoVirtualTrack.equivalent(compositions.get(i).getMarkerVirtualTrack())) {
          imfErrorLogger.addError(
              IMFErrorLogger.IMFErrors.ErrorCodes.IMF_CPL_ERROR,
              IMFErrorLogger.IMFErrors.ErrorLevels.WARNING,
              String.format(
                  "CPL Id %s can't be merged with Reference CPL Id %s, since the marker virtual tracks do not seem to represent the same timeline.",
                  compositions.get(i).getUUID(), referenceMarkerCPLUUID));
        }
      }
    }

    return imfErrorLogger.getErrors();
  }