code: public synchronized String apply(GenericMediaElement shaper, MediaType type) throws OpenViduException {
  		String id = shaper.getId();
  		if (id == null) {
  			throw new OpenViduException(Code.MEDIA_WEBRTC_ENDPOINT_ERROR_CODE,
  					"Unable to connect media element with null id");
  		}
  		if (elements.containsKey(id)) {
  			throw new OpenViduException(Code.MEDIA_WEBRTC_ENDPOINT_ERROR_CODE,
  					"This endpoint already has a media element with id " + id);
  		}
  		MediaElement first = null;
  		if (!elementIds.isEmpty()) {
  			first = elements.get(elementIds.getFirst());
  		}
  		if (connected) {
  			if (first != null) {
  				internalSinkConnect(first, shaper, type);
  			} else {
  				internalSinkConnect(this.getEndpoint(), shaper, type);
  			}
  			internalSinkConnect(shaper, passThru, type);
  		}
  		elementIds.addFirst(id);
  		elements.put(id, shaper);
  
  		this.filter = shaper;
  
  		elementsErrorSubscriptions.put(id, registerElemErrListener(shaper));
  		return id;
  	}
docs: Same as {@link #apply(MediaElement)}, can specify the media type that will be
  streamed through the shaper element.
  
  @param shaper {@link MediaElement} that will be linked to the end of the
  chain (e.g. a filter)
  @param type   indicates which type of media will be connected to the shaper
  ({@link MediaType}), if null then the connection is mixed
  @return the element's id
  @throws OpenViduException if thrown, the media element was not added