Package net.pms.configuration

Examples of net.pms.configuration.RendererConfiguration


   *         otherwise.
   *
   * @since 1.50.1
   */
  public boolean isCompatible(DLNAMediaInfo media, RendererConfiguration renderer) {
    RendererConfiguration referenceRenderer;

    if (renderer != null) {
      // Use the provided renderer as reference
      referenceRenderer = renderer;
    } else {
      // Use the default renderer as reference
      referenceRenderer = RendererConfiguration.getDefaultConf();
    }

    // Let the renderer configuration decide on native compatibility
    return referenceRenderer.isCompatible(media, this);
  }
View Full Code Here


      WebPlayer wp = new WebPlayer(WebPlayer.FLASH);
      return wp.launchTranscode(dlna, media, params);
    }
    params.minBufferSize = params.minFileSize;
    params.secondread_minsize = 100000;
    RendererConfiguration renderer = params.mediaRenderer;
    String filename = dlna.getSystemName();
    setAudioAndSubs(filename, media, params);

    // XXX work around an ffmpeg bug: http://ffmpeg.org/trac/ffmpeg/ticket/998
    if (filename.startsWith("mms:")) {
      filename = "mmsh:" + filename.substring(4);
    }

    // check if we have modifier for this url
    String r = replacements.match(filename);
    if (r != null) {
      filename = filename.replaceAll(r, replacements.get(r));
      LOGGER.debug("modified url: " + filename);
    }

    FFmpegOptions customOptions = new FFmpegOptions();

    // Gather custom options from various sources in ascending priority:
    // - automatic options
    String match = autoOptions.match(filename);
    if (match != null) {
      List<String> opts = autoOptions.get(match);
      if (opts != null) {
        customOptions.addAll(opts);
      }
    }
    // - (http) header options
    if (params.header != null && params.header.length > 0) {
      String hdr = new String(params.header);
      customOptions.addAll(parseOptions(hdr));
    }
    // - attached options
    String attached = (String) dlna.getAttachment(ID);
    if (attached != null) {
      customOptions.addAll(parseOptions(attached));
    }
    // - renderer options
    if (StringUtils.isNotEmpty(renderer.getCustomFFmpegOptions())) {
      customOptions.addAll(parseOptions(renderer.getCustomFFmpegOptions()));
    }

    // basename of the named pipe:
    // ffmpeg -loglevel warning -threads nThreads -i URL -threads nThreads -transcode-video-options /path/to/fifoName
    String fifoName = String.format(
View Full Code Here

          @Override
          public void run() {
            InetAddress rendererIp;
            try {
              rendererIp = InetAddress.getByName(rendererId);
              RendererConfiguration renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(rendererIp);
              String rendererName = "unknown renderer";
              try {
                rendererName = renderer.getRendererName().replaceAll("\n", "");
              } catch (NullPointerException e) { }
              LOGGER.info("Started playing " + getName() + " on your " + rendererName);
              LOGGER.debug("The full filename of which is: " + getSystemName() + " and the address of the renderer is: " + rendererId);
            } catch (UnknownHostException ex) {
              LOGGER.debug("" + ex);
View Full Code Here

            public void run() {
              if (refCount == 1) {
                InetAddress rendererIp;
                try {
                  rendererIp = InetAddress.getByName(rendererId);
                  RendererConfiguration renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(rendererIp);
                  String rendererName = "unknown renderer";
                  try {
                    rendererName = renderer.getRendererName();
                  } catch (NullPointerException e) { }
                  LOGGER.info("Stopped playing " + getName() + " on your " + rendererName);
                  LOGGER.debug("The full filename of which is: " + getSystemName() + " and the address of the renderer is: " + rendererId);
                } catch (UnknownHostException ex) {
                  LOGGER.debug("" + ex);
View Full Code Here

    try {
      int receivedContentLength = -1;
      String userAgentString = null;
      StringBuilder unknownHeaders = new StringBuilder();
      String separator = "";
      RendererConfiguration renderer = null;

      InetSocketAddress remoteAddress = (InetSocketAddress) socket.getRemoteSocketAddress();
      InetAddress ia = remoteAddress.getAddress();

      // Apply the IP filter
      if (filterIp(ia)) {
        throw new IOException("Access denied for address " + ia + " based on IP filter");
      }

      LOGGER.trace("Opened request handler on socket " + socket);
      PMS.get().getRegistry().disableGoToSleep();

      // The handler makes a couple of attempts to recognize a renderer from its requests.
      // IP address matches from previous requests are preferred, when that fails request
      // header matches are attempted and if those fail as well we're stuck with the
      // default renderer.

      // Attempt 1: try to recognize the renderer by its socket address from previous requests
      renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(ia);
      ArrayList<String> headerLines = new ArrayList<>();
      RendererConfiguration.SortedHeaderMap sortedHeaders = renderer == null ? new RendererConfiguration.SortedHeaderMap() : null;

      // Gather all the headers
      String line = br.readLine();
      while (line != null && line.length() > 0) {
        headerLines.add(line);
        if (renderer == null) {
          sortedHeaders.put(line);
        }
        line = br.readLine();
      }

      if (renderer == null) {
        // Attempt 2: try to recognize the renderer by matching headers
        renderer = RendererConfiguration.getRendererConfigurationByHeaders(sortedHeaders);
      }

      if (renderer != null) {
        renderer.associateIP(ia);
        PMS.get().setRendererFound(renderer);
      }

      for (String headerLine : headerLines) {
        LOGGER.trace("Received on socket: " + headerLine);

        // The request object is created inside the while loop.
        if (request != null && request.getMediaRenderer() == null && renderer != null) {
          request.setMediaRenderer(renderer);
        }
        if (headerLine.toUpperCase().startsWith("USER-AGENT")) {
          userAgentString = headerLine.substring(headerLine.indexOf(':') + 1).trim();
        }

        try {
          StringTokenizer s = new StringTokenizer(headerLine);
          String temp = s.nextToken();
          if (temp.equals("SUBSCRIBE") || temp.equals("GET") || temp.equals("POST") || temp.equals("HEAD")) {
            request = new Request(temp, s.nextToken().substring(1));
            if (s.hasMoreTokens() && s.nextToken().equals("HTTP/1.0")) {
              request.setHttp10(true);
            }
          } else if (request != null && temp.toUpperCase().equals("CALLBACK:")) {
            request.setSoapaction(s.nextToken());
          } else if (request != null && temp.toUpperCase().equals("SOAPACTION:")) {
            request.setSoapaction(s.nextToken());
          } else if (headerLine.toUpperCase().contains("CONTENT-LENGTH:")) {
            receivedContentLength = Integer.parseInt(headerLine.substring(headerLine.toUpperCase().indexOf("CONTENT-LENGTH: ") + 16));
          } else if (headerLine.toUpperCase().contains("RANGE: BYTES=")) {
            String nums = headerLine.substring(headerLine.toUpperCase().indexOf("RANGE: BYTES=") + 13).trim();
            StringTokenizer st = new StringTokenizer(nums, "-");
            if (!nums.startsWith("-")) {
              request.setLowRange(Long.parseLong(st.nextToken()));
            }
            if (!nums.startsWith("-") && !nums.endsWith("-")) {
              request.setHighRange(Long.parseLong(st.nextToken()));
            } else {
              request.setHighRange(-1);
            }
          } else if (headerLine.toLowerCase().contains("transfermode.dlna.org:")) {
            request.setTransferMode(headerLine.substring(headerLine.toLowerCase().indexOf("transfermode.dlna.org:") + 22).trim());
          } else if (headerLine.toLowerCase().contains("getcontentfeatures.dlna.org:")) {
            request.setContentFeatures(headerLine.substring(headerLine.toLowerCase().indexOf("getcontentfeatures.dlna.org:") + 28).trim());
          } else if (headerLine.toUpperCase().contains("TIMESEEKRANGE.DLNA.ORG: NPT=")) { // firmware 2.50+
            String timeseek = headerLine.substring(headerLine.toUpperCase().indexOf("TIMESEEKRANGE.DLNA.ORG: NPT=") + 28);
            if (timeseek.endsWith("-")) {
              timeseek = timeseek.substring(0, timeseek.length() - 1);
            } else if (timeseek.indexOf('-') > -1) {
              timeseek = timeseek.substring(0, timeseek.indexOf('-'));
            }
            request.setTimeseek(convertStringToTime(timeseek));
          } else if (headerLine.toUpperCase().contains("TIMESEEKRANGE.DLNA.ORG : NPT=")) { // firmware 2.40
            String timeseek = headerLine.substring(headerLine.toUpperCase().indexOf("TIMESEEKRANGE.DLNA.ORG : NPT=") + 29);
            if (timeseek.endsWith("-")) {
              timeseek = timeseek.substring(0, timeseek.length() - 1);
            } else if (timeseek.indexOf('-') > -1) {
              timeseek = timeseek.substring(0, timeseek.indexOf('-'));
            }
            request.setTimeseek(convertStringToTime(timeseek));
          } else {
            /*
             * If we made it to here, none of the previous header checks matched.
             * Unknown headers make interesting logging info when we cannot recognize
             * the media renderer, so keep track of the truly unknown ones.
             */
            boolean isKnown = false;

            // Try to match possible known headers.
            String lowerCaseHeaderLine = headerLine.toLowerCase();
            for (String knownHeaderString : KNOWN_HEADERS) {
              if (lowerCaseHeaderLine.startsWith(knownHeaderString.toLowerCase())) {
                isKnown = true;
                break;
              }
            }

            // It may be unusual but already known
            if (renderer != null) {
              String additionalHeader = renderer.getUserAgentAdditionalHttpHeader();
              if (StringUtils.isNotBlank(additionalHeader) && lowerCaseHeaderLine.startsWith(additionalHeader)) {
                isKnown = true;
              }
            }

View Full Code Here

   */
  public List<String> getVideoFilterOptions(DLNAResource dlna, DLNAMediaInfo media, OutputParams params) throws IOException {
    List<String> videoFilterOptions = new ArrayList<>();
    ArrayList<String> filterChain = new ArrayList<>();
    ArrayList<String> scalePadFilterChain = new ArrayList<>();
    final RendererConfiguration renderer = params.mediaRenderer;

    boolean isMediaValid = media != null && media.isMediaparsed() && media.getHeight() != 0;
    boolean isResolutionTooHighForRenderer = renderer.isMaximumResolutionSpecified() && isMediaValid && // renderer defines a max width/height
      (
        media.getWidth() > renderer.getMaxVideoWidth() ||
        media.getHeight() > renderer.getMaxVideoHeight()
      );

    int scaleWidth = 0;
    int scaleHeight = 0;
    if (media.getWidth() > 0 && media.getHeight() > 0) {
      scaleWidth = media.getWidth();
      scaleHeight = media.getHeight();
    }

    boolean is3D = media.is3d() && !media.stereoscopyIsAnaglyph();

    // Make sure the aspect ratio is 16/9 if the renderer needs it.
    boolean keepAR = renderer.isKeepAspectRatio() &&
        !media.is3dFullSbsOrOu() &&
        !"16:9".equals(media.getAspectRatioContainer());

    // Scale and pad the video if necessary
    if (isResolutionTooHighForRenderer || (!renderer.isRescaleByRenderer() && renderer.isMaximumResolutionSpecified() && media.getWidth() < 720)) { // Do not rescale for SD video and higher
      if (media.is3dFullSbsOrOu()) {
        scalePadFilterChain.add(String.format("scale=%1$d:%2$d", renderer.getMaxVideoWidth(), renderer.getMaxVideoHeight()));
      } else {
        scalePadFilterChain.add(String.format("scale=iw*min(%1$d/iw\\,%2$d/ih):ih*min(%1$d/iw\\,%2$d/ih)", renderer.getMaxVideoWidth(), renderer.getMaxVideoHeight()));

        if (keepAR) {
          scalePadFilterChain.add(String.format("pad=%1$d:%2$d:(%1$d-iw)/2:(%2$d-ih)/2", renderer.getMaxVideoWidth(), renderer.getMaxVideoHeight()));
        }
      }
    } else if (keepAR && isMediaValid) {
      if ((media.getWidth() / (double) media.getHeight()) >= (16 / (double) 9)) {
        scalePadFilterChain.add("pad=iw:iw/(16/9):0:(oh-ih)/2");
        scaleHeight = (int) Math.round(scaleWidth / (16 / (double) 9));
      } else {
        scalePadFilterChain.add("pad=ih*(16/9):ih:(ow-iw)/2:0");
        scaleWidth = (int) Math.round(scaleHeight * (16 / (double) 9));
      }

      scaleWidth  = convertToModX(scaleWidth, 4);
      scaleHeight = convertToModX(scaleHeight, 4);

      // Make sure we didn't exceed the renderer's maximum resolution.
      if (
        scaleHeight > renderer.getMaxVideoHeight() ||
        scaleWidth  > renderer.getMaxVideoWidth()
      ) {
        scaleHeight = renderer.getMaxVideoHeight();
        scaleWidth  = renderer.getMaxVideoWidth();
      }

      scalePadFilterChain.add("scale=" + scaleWidth + ":" + scaleHeight);
    }

    if (!isDisableSubtitles(params) && !(dlna.getPlayer() instanceof WebPlayer)) {
      StringBuilder subsFilter = new StringBuilder();
      if (params.sid.getType().isText()) {
        String originalSubsFilename;
        String subsFilename;
        if (params.sid.isEmbedded() || configuration.isFFmpegFontConfig() || is3D) {
          originalSubsFilename = SubtitleUtils.getSubtitles(dlna, media, params, configuration, SubtitleType.ASS).getAbsolutePath();
        } else {
          originalSubsFilename = params.sid.getExternalFile().getAbsolutePath();
        }

        if (originalSubsFilename != null) {
          StringBuilder s = new StringBuilder();
          CharacterIterator it = new StringCharacterIterator(originalSubsFilename);
          for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) {
            switch (ch) {
              case ':':
                s.append("\\\\:");
                break;
              case '\\':
                s.append("/");
                break;
              case ']':
              case '[':
                s.append("\\");
              default:
                s.append(ch);
                break;
            }
          }

          subsFilename = s.toString();
          subsFilename = subsFilename.replace(",", "\\,");
          subsFilter.append("subtitles=").append(subsFilename);

          // Set the resolution for subtitles to use
          int subtitlesWidth = scaleWidth;
          int subtitlesHeight = scaleHeight;
          if (params.sid.isExternal() && params.sid.getType() != SubtitleType.ASS || configuration.isFFmpegFontConfig()) {
            if (subtitlesWidth > 0 && subtitlesHeight > 0) {
              // Let ASS/SSA subtitles specify their own resolution
              if (params.sid.getType() == SubtitleType.ASS) {
                setSubtitlesResolution(originalSubsFilename, subtitlesWidth, subtitlesHeight);
              }

              if (!is3D) {
                subsFilter.append(":").append(subtitlesWidth).append("x").append(subtitlesHeight);
              }

              // Set the input subtitles character encoding if not UTF-8
              if (!params.sid.isExternalFileUtf8()) {
                String encoding = isNotBlank(configuration.getSubtitlesCodepage()) ?
                    configuration.getSubtitlesCodepage() : params.sid.getExternalFileCharacterSet() != null ?
                    params.sid.getExternalFileCharacterSet() : null;
                if (encoding != null) {
                  subsFilter.append(":").append(encoding);
                }
              }
            }
          }
        }
      } else if (params.sid.getType().isPicture()) {
        if (params.sid.getId() < 100) {
          // Embedded
          subsFilter.append("[0:v][0:s:").append(media.getSubtitleTracksList().indexOf(params.sid)).append("]overlay");
        } else {
          // External
          videoFilterOptions.add("-i");
          videoFilterOptions.add(params.sid.getExternalFile().getAbsolutePath());
          subsFilter.append("[0:v][1:s]overlay"); // this assumes the sub file is single-language
        }
      }

      if (isNotBlank(subsFilter)) {
        filterChain.add(subsFilter.toString());
        // based on https://trac.ffmpeg.org/ticket/2067
        if (params.timeseek > 0) {
          videoFilterOptions.add("-copyts");
          videoFilterOptions.add("-copypriorss");
          videoFilterOptions.add("0");
          videoFilterOptions.add("-avoid_negative_ts");
          videoFilterOptions.add("1");
          videoFilterOptions.add("-af");
          videoFilterOptions.add("asetpts=PTS-" + params.timeseek + "/TB");
          filterChain.add("setpts=PTS-" + params.timeseek + "/TB");
        }
      }
    }

    String overrideVF = renderer.getFFmpegVideoFilterOverride();
    if (StringUtils.isNotEmpty(overrideVF)) {
      filterChain.add(overrideVF);
    } else {
      filterChain.addAll(scalePadFilterChain);
    }
View Full Code Here

   * to its <code>TranscodeVideo</code> profile.
   */
  public synchronized List<String> getVideoTranscodeOptions(DLNAResource dlna, DLNAMediaInfo media, OutputParams params) {
    List<String> transcodeOptions = new ArrayList<>();
    final String filename = dlna.getSystemName();
    final RendererConfiguration renderer = params.mediaRenderer;
    String customFFmpegOptions = renderer.getCustomFFmpegOptions();

    if (
      (
        renderer.isTranscodeToWMV() &&
        !renderer.isXbox360()
      ) ||
      (
        renderer.isXboxOne() &&
        purpose() == VIDEO_WEBSTREAM_PLAYER
      )
    ) { // WMV
      transcodeOptions.add("-c:v");
      transcodeOptions.add("wmv2");

      if (!customFFmpegOptions.contains("-c:a ")) {
        transcodeOptions.add("-c:a");
        transcodeOptions.add("wmav2");
      }

      transcodeOptions.add("-f");
      transcodeOptions.add("asf");
    } else { // MPEGPSMPEG2AC3, MPEGTSMPEG2AC3, MPEGTSH264AC3 or MPEGTSH264AAC
      final boolean isTsMuxeRVideoEngineEnabled = configuration.getEnginesAsList(PMS.get().getRegistry()).contains(TsMuxeRVideo.ID);

      // Output audio codec
      dtsRemux = isTsMuxeRVideoEngineEnabled &&
        configuration.isAudioEmbedDtsInPcm() &&
        params.aid != null &&
        params.aid.isDTS() &&
        !avisynth() &&
        renderer.isDTSPlayable();
     
      boolean isSubtitlesAndTimeseek = !isDisableSubtitles(params) && params.timeseek > 0;

      if (configuration.isAudioRemuxAC3() && params.aid != null && params.aid.isAC3() && !avisynth() && renderer.isTranscodeToAC3() && !isSubtitlesAndTimeseek) {
        // AC-3 remux
        if (!customFFmpegOptions.contains("-c:a ")) {
          transcodeOptions.add("-c:a");
          transcodeOptions.add("copy");
        }
      } else {
        if (dtsRemux) {
          // Audio is added in a separate process later
          transcodeOptions.add("-an");
        } else if (type() == Format.AUDIO) {
          // Skip
        } else if (renderer.isTranscodeToAAC()) {
          transcodeOptions.add("-c:a");
          transcodeOptions.add("aac");

          transcodeOptions.add("-strict");
          transcodeOptions.add("experimental");
        } else {
          if (!customFFmpegOptions.contains("-c:a ")) {
            transcodeOptions.add("-c:a");
            transcodeOptions.add("ac3");
          }
        }
      }

      InputFile newInput = null;
      if (filename != null) {
        newInput = new InputFile();
        newInput.setFilename(filename);
        newInput.setPush(params.stdin);
      }

      // Output video codec
      if (renderer.isTranscodeToH264()) {
        transcodeOptions.add("-c:v");
        transcodeOptions.add("libx264");
        transcodeOptions.add("-preset");
        transcodeOptions.add("ultrafast");
        transcodeOptions.add("-level");
        transcodeOptions.add("31");
        transcodeOptions.add("-pix_fmt");
        transcodeOptions.add("yuv420p");
      } else if (!dtsRemux) {
        transcodeOptions.add("-c:v");
        transcodeOptions.add("mpeg2video");
      }

      // Output file format
      transcodeOptions.add("-f");
      if (dtsRemux) {
        transcodeOptions.add("mpeg2video");
      } else if (renderer.isTranscodeToMPEGTS()) {
        transcodeOptions.add("mpegts");
      } else {
        transcodeOptions.add("vob");
      }
    }
View Full Code Here

        nThreads = configuration.getNumberOfCpuCores();
      }
    }

    List<String> cmdList = new ArrayList<>();
    RendererConfiguration renderer = params.mediaRenderer;
    boolean avisynth = avisynth();
    if (params.timeseek > 0) {
      params.waitbeforestart = 200;
    } else {
      params.waitbeforestart = 2500;
    }

    setAudioAndSubs(filename, media, params);
    cmdList.add(executable());

    // Prevent FFmpeg timeout
    cmdList.add("-y");

    cmdList.add("-loglevel");
    if (LOGGER.isTraceEnabled()) { // Set -loglevel in accordance with LOGGER setting
      cmdList.add("verbose"); // Could be changed to "verbose" or "debug" if "info" level is not enough
    } else {
      cmdList.add("fatal");
    }

    if (params.timeseek > 0) {
      cmdList.add("-ss");
      cmdList.add(String.valueOf((int) params.timeseek));
    }

    // Decoder threads
    if (nThreads > 0) {
      cmdList.add("-threads");
      cmdList.add(String.valueOf(nThreads));
    }

    final boolean isTsMuxeRVideoEngineEnabled = configuration.getEnginesAsList(PMS.get().getRegistry()).contains(TsMuxeRVideo.ID);
    final boolean isXboxOneWebVideo = params.mediaRenderer.isXboxOne() && purpose() == VIDEO_WEBSTREAM_PLAYER;

    ac3Remux = false;
    dtsRemux = false;

    if (
      configuration.isAudioRemuxAC3() &&
      params.aid != null &&
      params.aid.isAC3() &&
      !avisynth() &&
      renderer.isTranscodeToAC3() &&
      !isXboxOneWebVideo
    ) {
      // AC-3 remux takes priority
      ac3Remux = true;
    } else {
      // Now check for DTS remux and LPCM streaming
      dtsRemux = isTsMuxeRVideoEngineEnabled &&
        configuration.isAudioEmbedDtsInPcm() &&
        params.aid != null &&
        params.aid.isDTS() &&
        !avisynth() &&
        params.mediaRenderer.isDTSPlayable();
    }

    String frameRateRatio = media.getValidFps(true);
    String frameRateNumber = media.getValidFps(false);

    // Input filename
    cmdList.add("-i");
    if (avisynth && !filename.toLowerCase().endsWith(".iso")) {
      File avsFile = AviSynthFFmpeg.getAVSScript(filename, params.sid, params.fromFrame, params.toFrame, frameRateRatio, frameRateNumber);
      cmdList.add(ProcessUtil.getShortFileNameIfWideChars(avsFile.getAbsolutePath()));
    } else {
      cmdList.add(filename);
    }

    /**
     * Defer to MEncoder for subtitles if:
     * - The setting is enabled or embedded fonts exist
     * - There are subtitles to transcode
     * - The file is not being played via the transcode folder
     */
    String prependTraceReason = "Switching from FFmpeg to MEncoder to transcode subtitles because ";
    if (
      params.sid != null &&
      !(
        !configuration.getHideTranscodeEnabled() &&
        dlna.isNoName() &&
        (dlna.getParent() instanceof FileTranscodeVirtualFolder)
      )
    ) {
      boolean deferToMencoder = false;
      if (configuration.isFFmpegDeferToMEncoderForSubtitles()) {
        deferToMencoder = true;
        LOGGER.trace(prependTraceReason + "the user setting is enabled.");
      } else if (media.isEmbeddedFontExists()) {
        deferToMencoder = true;
        LOGGER.trace(prependTraceReason + "there are embedded fonts.");
      }
      if (deferToMencoder) {
        MEncoderVideo mv = new MEncoderVideo();
        return mv.launchTranscode(dlna, media, params);
      }
    }

    // Decide whether to defer to tsMuxeR or continue to use FFmpeg
    boolean deferToTsmuxer = true;
    prependTraceReason = "Not muxing the video stream with tsMuxeR via FFmpeg because ";
    if (!configuration.isFFmpegMuxWithTsMuxerWhenCompatible()) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "the user setting is disabled");
    }
    if (deferToTsmuxer == true && !configuration.getHideTranscodeEnabled() && dlna.isNoName() && (dlna.getParent() instanceof FileTranscodeVirtualFolder)) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "the file is being played via a FFmpeg entry in the transcode folder.");
    }
    if (deferToTsmuxer == true && !params.mediaRenderer.isMuxH264MpegTS()) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "the renderer does not support H.264 inside MPEG-TS.");
    }
    if (deferToTsmuxer == true && params.sid != null) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "we need to burn subtitles.");
    }
    if (deferToTsmuxer == true && avisynth()) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "we are using AviSynth.");
    }
    if (deferToTsmuxer == true && params.mediaRenderer.isH264Level41Limited() && !media.isVideoWithinH264LevelLimits(newInput, params.mediaRenderer)) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "the video stream is not within H.264 level limits for this renderer.");
    }
    if (deferToTsmuxer == true && !media.isMuxable(params.mediaRenderer)) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "the video stream is not muxable to this renderer");
    }
    if (deferToTsmuxer == true && !aspectRatiosMatch) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "we need to transcode to apply the correct aspect ratio.");
    }
    if (deferToTsmuxer == true && !params.mediaRenderer.isPS3() && filename.contains("WEB-DL")) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "the version of tsMuxeR supported by this renderer does not support WEB-DL files.");
    }
    if (deferToTsmuxer == true && "bt.601".equals(media.getMatrixCoefficients())) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "the colorspace probably isn't supported by the renderer.");
    }
    if (deferToTsmuxer == true && params.mediaRenderer.isKeepAspectRatio() && !"16:9".equals(media.getAspectRatioContainer())) {
      deferToTsmuxer = false;
      LOGGER.trace(prependTraceReason + "the renderer needs us to add borders so it displays the correct aspect ratio of " + media.getAspectRatioContainer() + ".");
    }
    if (deferToTsmuxer) {
      TsMuxeRVideo tv = new TsMuxeRVideo();
      params.forceFps = media.getValidFps(false);

      if (media.getCodecV() != null) {
        if (media.isH264()) {
          params.forceType = "V_MPEG4/ISO/AVC";
        } else if (media.getCodecV().startsWith("mpeg2")) {
          params.forceType = "V_MPEG-2";
        } else if (media.getCodecV().equals("vc1")) {
          params.forceType = "V_MS/VFW/WVC1";
        }
      }

      return tv.launchTranscode(dlna, media, params);
    }

    // Apply any video filters and associated options. These should go
    // after video input is specified and before output streams are mapped.
    cmdList.addAll(getVideoFilterOptions(dlna, media, params));

    // Map the output streams if necessary
    if (media.getAudioTracksList().size() > 1) {
      // Set the video stream
      cmdList.add("-map");
      cmdList.add("0:v");

      // Set the proper audio stream
      cmdList.add("-map");
      cmdList.add("0:a:" + (media.getAudioTracksList().indexOf(params.aid)));
    }

    // Now configure the output streams

    // Encoder threads
    if (nThreads > 0) {
      cmdList.add("-threads");
      cmdList.add(String.valueOf(nThreads));
    }

    if (params.timeend > 0) {
      cmdList.add("-t");
      cmdList.add(String.valueOf(params.timeend));
    }

    cmdList.addAll(getVideoBitrateOptions(dlna, media, params));

    // add audio bitrate options
    // TODO: Integrate our (more comprehensive) code with this function
    // from PMS to make keeping synchronised easier.
    // Until then, leave the following line commented out.
    // cmdList.addAll(getAudioBitrateOptions(dlna, media, params));

    String customFFmpegOptions = renderer.getCustomFFmpegOptions();

    // Audio bitrate
    if (!ac3Remux && !dtsRemux && !(type() == Format.AUDIO)) {
      int channels = 0;
      if (
        (
          renderer.isTranscodeToWMV() &&
          !renderer.isXbox360()
        ) ||
        (
          renderer.isXboxOne() &&
          purpose() == VIDEO_WEBSTREAM_PLAYER
        )
      ) {
        channels = 2;
      } else if (params.aid != null && params.aid.getAudioProperties().getNumberOfChannels() > configuration.getAudioChannelCount()) {
        channels = configuration.getAudioChannelCount();
      }

      if (!customFFmpegOptions.contains("-ac ") && channels > 0) {
        cmdList.add("-ac");
        cmdList.add(String.valueOf(channels));
      }

      if (!customFFmpegOptions.contains("-ab ")) {
        cmdList.add("-ab");
        if (renderer.isTranscodeToAAC()) {
          cmdList.add(Math.min(configuration.getAudioBitrate(), 320) + "k");
        } else {
          cmdList.add(String.valueOf(CodecUtil.getAC3Bitrate(configuration, params.aid)) + "k");
        }
      }
    }

    // Add the output options (-f, -c:a, -c:v, etc.)
    cmdList.addAll(getVideoTranscodeOptions(dlna, media, params));

    // Add custom options
    if (StringUtils.isNotEmpty(customFFmpegOptions)) {
      parseOptions(customFFmpegOptions, cmdList);
    }

    if (!dtsRemux) {
      cmdList.add("pipe:");
    }

    String[] cmdArray = new String[cmdList.size()];
    cmdList.toArray(cmdArray);

    cmdArray = finalizeTranscoderArgs(
      filename,
      dlna,
      media,
      params,
      cmdArray
    );

    ProcessWrapperImpl pw = new ProcessWrapperImpl(cmdArray, params);

    setOutputParsing(dlna, pw, false);

    if (dtsRemux) {
      PipeProcess pipe;
      pipe = new PipeProcess(System.currentTimeMillis() + "tsmuxerout.ts");

      TsMuxeRVideo ts = new TsMuxeRVideo();
      File f = new File(configuration.getTempFolder(), "pms-tsmuxer.meta");
      String cmd[] = new String[]{ ts.executable(), f.getAbsolutePath(), pipe.getInputPipe() };
      pw = new ProcessWrapperImpl(cmd, params);

      PipeIPCProcess ffVideoPipe = new PipeIPCProcess(System.currentTimeMillis() + "ffmpegvideo", System.currentTimeMillis() + "videoout", false, true);

      cmdList.add(ffVideoPipe.getInputPipe());

      OutputParams ffparams = new OutputParams(configuration);
      ffparams.maxBufferSize = 1;
      ffparams.stdin = params.stdin;

      String[] cmdArrayDts = new String[cmdList.size()];
      cmdList.toArray(cmdArrayDts);

      cmdArrayDts = finalizeTranscoderArgs(
        filename,
        dlna,
        media,
        params,
        cmdArrayDts
      );

      ProcessWrapperImpl ffVideo = new ProcessWrapperImpl(cmdArrayDts, ffparams);

      ProcessWrapper ff_video_pipe_process = ffVideoPipe.getPipeProcess();
      pw.attachProcess(ff_video_pipe_process);
      ff_video_pipe_process.runInNewThread();
      ffVideoPipe.deleteLater();

      pw.attachProcess(ffVideo);
      ffVideo.runInNewThread();

      PipeIPCProcess ffAudioPipe = new PipeIPCProcess(System.currentTimeMillis() + "ffmpegaudio01", System.currentTimeMillis() + "audioout", false, true);
      StreamModifier sm = new StreamModifier();
      sm.setPcm(false);
      sm.setDtsEmbed(dtsRemux);
      sm.setSampleFrequency(48000);
      sm.setBitsPerSample(16);
      sm.setNbChannels(2);

      List<String> cmdListDTS = new ArrayList<>();
      cmdListDTS.add(executable());
      cmdListDTS.add("-y");
      cmdListDTS.add("-ss");

      if (params.timeseek > 0) {
        cmdListDTS.add(String.valueOf(params.timeseek));
      } else {
        cmdListDTS.add("0");
      }

      if (params.stdin == null) {
        cmdListDTS.add("-i");
      } else {
        cmdListDTS.add("-");
      }
      cmdListDTS.add(filename);

      if (params.timeseek > 0) {
        cmdListDTS.add("-copypriorss");
        cmdListDTS.add("0");
        cmdListDTS.add("-avoid_negative_ts");
        cmdListDTS.add("1");
      }

      cmdListDTS.add("-ac");
      cmdListDTS.add("2");

      cmdListDTS.add("-f");
      cmdListDTS.add("dts");

      cmdListDTS.add("-c:a");
      cmdListDTS.add("copy");

      cmdListDTS.add(ffAudioPipe.getInputPipe());

      String[] cmdArrayDTS = new String[cmdListDTS.size()];
      cmdListDTS.toArray(cmdArrayDTS);

      if (!params.mediaRenderer.isMuxDTSToMpeg()) { // No need to use the PCM trick when media renderer supports DTS
        ffAudioPipe.setModifier(sm);
      }

      OutputParams ffaudioparams = new OutputParams(configuration);
      ffaudioparams.maxBufferSize = 1;
      ffaudioparams.stdin = params.stdin;
      ProcessWrapperImpl ffAudio = new ProcessWrapperImpl(cmdArrayDTS, ffaudioparams);

      params.stdin = null;
      try (PrintWriter pwMux = new PrintWriter(f)) {
        pwMux.println("MUXOPT --no-pcr-on-video-pid --no-asyncio --new-audio-pes --vbr --vbv-len=500");
        String videoType = "V_MPEG-2";

        if (renderer.isTranscodeToH264()) {
          videoType = "V_MPEG4/ISO/AVC";
        }

        if (params.no_videoencode && params.forceType != null) {
          videoType = params.forceType;
View Full Code Here

  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
    throws Exception {
    RequestV2 request = null;
    RendererConfiguration renderer = null;
    String userAgentString = null;
    StringBuilder unknownHeaders = new StringBuilder();
    String separator = "";

    HttpRequest nettyRequest = this.nettyRequest = (HttpRequest) e.getMessage();

    InetSocketAddress remoteAddress = (InetSocketAddress) e.getChannel().getRemoteAddress();
    InetAddress ia = remoteAddress.getAddress();

    // Apply the IP filter
    if (filterIp(ia)) {
      e.getChannel().close();
      LOGGER.trace("Access denied for address " + ia + " based on IP filter");
      return;
    }

    LOGGER.trace("Opened request handler on socket " + remoteAddress);
    PMS.get().getRegistry().disableGoToSleep();
    request = new RequestV2(nettyRequest.getMethod().getName(), nettyRequest.getUri().substring(1));
    LOGGER.trace("Request: " + nettyRequest.getProtocolVersion().getText() + " : " + request.getMethod() + " : " + request.getArgument());

    if (nettyRequest.getProtocolVersion().getMinorVersion() == 0) {
      request.setHttp10(true);
    }

    HttpHeaders headers = nettyRequest.headers();

    // The handler makes a couple of attempts to recognize a renderer from its requests.
    // IP address matches from previous requests are preferred, when that fails request
    // header matches are attempted and if those fail as well we're stuck with the
    // default renderer.

    // Attempt 1: try to recognize the renderer by its socket address from previous requests
    renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(ia);

    if (renderer == null) {
      // Attempt 2: try to recognize the renderer by matching headers
      renderer = RendererConfiguration.getRendererConfigurationByHeaders(headers.entries());
    }

    if (renderer != null) {
      renderer.associateIP(ia);
      PMS.get().setRendererFound(renderer);
      request.setMediaRenderer(renderer);
    }

    Set<String> headerNames = headers.names();
    Iterator<String> iterator = headerNames.iterator();
    while (iterator.hasNext()) {
      String name = iterator.next();
      String headerLine = name + ": " + headers.get(name);
      LOGGER.trace("Received on socket: " + headerLine);

      if (headerLine.toUpperCase().startsWith("USER-AGENT")) {
        userAgentString = headerLine.substring(headerLine.indexOf(':') + 1).trim();
      }

      try {
        StringTokenizer s = new StringTokenizer(headerLine);
        String temp = s.nextToken();
        if (temp.toUpperCase().equals("SOAPACTION:")) {
          request.setSoapaction(s.nextToken());
        } else if (temp.toUpperCase().equals("CALLBACK:")) {
          request.setSoapaction(s.nextToken());
        } else if (headerLine.toUpperCase().contains("RANGE: BYTES=")) {
          String nums = headerLine.substring(
            headerLine.toUpperCase().indexOf(
            "RANGE: BYTES=") + 13).trim();
          StringTokenizer st = new StringTokenizer(nums, "-");
          if (!nums.startsWith("-")) {
            request.setLowRange(Long.parseLong(st.nextToken()));
          }
          if (!nums.startsWith("-") && !nums.endsWith("-")) {
            request.setHighRange(Long.parseLong(st.nextToken()));
          } else {
            request.setHighRange(-1);
          }
        } else if (headerLine.toLowerCase().contains("transfermode.dlna.org:")) {
          request.setTransferMode(headerLine.substring(headerLine.toLowerCase().indexOf("transfermode.dlna.org:") + 22).trim());
        } else if (headerLine.toLowerCase().contains("getcontentfeatures.dlna.org:")) {
          request.setContentFeatures(headerLine.substring(headerLine.toLowerCase().indexOf("getcontentfeatures.dlna.org:") + 28).trim());
        } else {
          Matcher matcher = TIMERANGE_PATTERN.matcher(headerLine);
          if (matcher.find()) {
            String first = matcher.group(1);
            if (first != null) {
              request.setTimeRangeStartString(first);
            }
            String end = matcher.group(2);
            if (end != null) {
              request.setTimeRangeEndString(end);
            }
          } else {
            /** If we made it to here, none of the previous header checks matched.
             * Unknown headers make interesting logging info when we cannot recognize
             * the media renderer, so keep track of the truly unknown ones.
             */
            boolean isKnown = false;

            // Try to match known headers.
            String lowerCaseHeaderLine = headerLine.toLowerCase();
            for (String knownHeaderString : KNOWN_HEADERS) {
              if (lowerCaseHeaderLine.startsWith(knownHeaderString)) {
                isKnown = true;
                break;
              }
            }

            // It may be unusual but already known
            if (renderer != null) {
              String additionalHeader = renderer.getUserAgentAdditionalHttpHeader();
              if (StringUtils.isNotBlank(additionalHeader) && lowerCaseHeaderLine.startsWith(additionalHeader)) {
                isKnown = true;
              }
            }

View Full Code Here

  @Override
  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
    throws Exception {
    RequestV2 request = null;
    RendererConfiguration renderer = null;
    String userAgentString = null;
    StringBuilder unknownHeaders = new StringBuilder();
    String separator = "";
   
    HttpRequest nettyRequest = this.nettyRequest = (HttpRequest) e.getMessage();

    InetSocketAddress remoteAddress = (InetSocketAddress) e.getChannel().getRemoteAddress();
    InetAddress ia = remoteAddress.getAddress();

    // Apply the IP filter
    if (filterIp(ia)) {
      e.getChannel().close();
      logger.trace("Access denied for address " + ia + " based on IP filter");
      return;
    }

    logger.trace("Opened request handler on socket " + remoteAddress);
    PMS.get().getRegistry().disableGoToSleep();

    if (HttpMethod.GET.equals(nettyRequest.getMethod())) {
      request = new RequestV2("GET", nettyRequest.getUri().substring(1));
    } else if (HttpMethod.POST.equals(nettyRequest.getMethod())) {
      request = new RequestV2("POST", nettyRequest.getUri().substring(1));
    } else if (HttpMethod.HEAD.equals(nettyRequest.getMethod())) {
      request = new RequestV2("HEAD", nettyRequest.getUri().substring(1));
    } else {
      request = new RequestV2(nettyRequest.getMethod().getName(), nettyRequest.getUri().substring(1));
    }

    logger.trace("Request: " + nettyRequest.getProtocolVersion().getText() + " : " + request.getMethod() + " : " + request.getArgument());

    if (nettyRequest.getProtocolVersion().getMinorVersion() == 0) {
      request.setHttp10(true);
    }

    // The handler makes a couple of attempts to recognize a renderer from its requests.
    // IP address matches from previous requests are preferred, when that fails request
    // header matches are attempted and if those fail as well we're stuck with the
    // default renderer.

    // Attempt 1: try to recognize the renderer by its socket address
    renderer = RendererConfiguration.getRendererConfigurationBySocketAddress(ia);

    if (renderer != null) {
      PMS.get().setRendererFound(renderer);
      request.setMediaRenderer(renderer);
      logger.trace("Matched media renderer \"" + renderer.getRendererName() + "\" based on address " + ia);
    }
   
    for (String name : nettyRequest.getHeaderNames()) {
      String headerLine = name + ": " + nettyRequest.getHeader(name);
      logger.trace("Received on socket: " + headerLine);

      if (renderer == null && headerLine != null
          && headerLine.toUpperCase().startsWith("USER-AGENT")
          && request != null) {
        userAgentString = headerLine.substring(headerLine.indexOf(":") + 1).trim();

        // Attempt 2: try to recognize the renderer by matching the "User-Agent" header
        renderer = RendererConfiguration.getRendererConfigurationByUA(userAgentString);

        if (renderer != null) {
          request.setMediaRenderer(renderer);
          renderer.associateIP(ia)// Associate IP address for later requests
          PMS.get().setRendererFound(renderer);
          logger.trace("Matched media renderer \"" + renderer.getRendererName() + "\" based on header \"" + headerLine + "\"");
        }
      }

      if (renderer == null && headerLine != null && request != null) {
        // Attempt 3: try to recognize the renderer by matching an additional header
        renderer = RendererConfiguration.getRendererConfigurationByUAAHH(headerLine);

        if (renderer != null) {
          request.setMediaRenderer(renderer);
          renderer.associateIP(ia)// Associate IP address for later requests
          PMS.get().setRendererFound(renderer);
          logger.trace("Matched media renderer \"" + renderer.getRendererName() + "\" based on header \"" + headerLine + "\"");
        }
      }

      try {
        StringTokenizer s = new StringTokenizer(headerLine);
View Full Code Here

TOP

Related Classes of net.pms.configuration.RendererConfiguration

Copyright © 2018 www.massapicom. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.