Package com.kurento.kmf.content.internal.base

Source Code of com.kurento.kmf.content.internal.base.AbstractSdpContentSession

/*
* (C) Copyright 2013 Kurento (http://kurento.org/)
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*/
package com.kurento.kmf.content.internal.base;

import javax.servlet.AsyncContext;

import com.kurento.kmf.common.exception.Assert;
import com.kurento.kmf.common.exception.KurentoMediaFrameworkException;
import com.kurento.kmf.content.ContentHandler;
import com.kurento.kmf.content.ContentSession;
import com.kurento.kmf.content.SdpContentSession;
import com.kurento.kmf.content.internal.ContentSessionManager;
import com.kurento.kmf.content.jsonrpc.JsonRpcRequest;
import com.kurento.kmf.content.jsonrpc.JsonRpcResponse;
import com.kurento.kmf.media.MediaElement;
import com.kurento.kmf.media.MediaPipeline;
import com.kurento.kmf.media.PlayerEndpoint;
import com.kurento.kmf.media.RecorderEndpoint;
import com.kurento.kmf.media.SdpEndpoint;
import com.kurento.kmf.media.events.ErrorEvent;
import com.kurento.kmf.media.events.MediaEventListener;
import com.kurento.kmf.media.events.MediaSessionStartedEvent;
import com.kurento.kmf.media.events.MediaSessionTerminatedEvent;
import com.kurento.kmf.repository.RepositoryHttpPlayer;
import com.kurento.kmf.repository.RepositoryHttpRecorder;
import com.kurento.kmf.repository.RepositoryItem;

/**
*
* Extension of Content Request to support encapsulated SDP in requests.
*
* @author Luis López (llopez@gsyc.es)
* @version 1.0.0
*/
public abstract class AbstractSdpContentSession extends AbstractContentSession
    implements SdpContentSession {

  /**
   * Parameterized constructor; initial state here is HANDLING.
   *
   * @param manager
   *            Content request manager
   * @param asyncContext
   *            Asynchronous context
   * @param contentId
   *            Content identifier
   */

  private RepositoryHttpPlayer repositoryHttpPlayer;
  private RepositoryHttpRecorder repositoryHttpRecorder;

  public AbstractSdpContentSession(
      ContentHandler<? extends ContentSession> handler,
      ContentSessionManager manager, AsyncContext asyncContext,
      String contentId) {
    super(handler, manager, asyncContext, contentId);
  }

  @Override
  protected void processStartJsonRpcRequest(AsyncContext asyncCtx,
      JsonRpcRequest message) {
    Assert.notNull(
        initialJsonRequest.getParams().getSdp(),
        "SDP cannot be null on message with method "
            + message.getMethod(), 10024);
    super.processStartJsonRpcRequest(asyncCtx, message);
  }

  /**
   * Build an end point for SDP declaration in a MediaPipeline.
   *
   * @param mediaPipeline
   *            a MediaPipeline for which the SdpEndpoint is created
   * @return a SdpEndpoint
   * @throws Throwable
   *             Error/Exception
   */
  protected abstract SdpEndpoint buildSdpEndpoint(MediaPipeline mediaPipeline);

  /**
   * Star media element implementation.
   *
   * @param sourceContentPath
   *            Path of outgoing media element
   * @param sinkContentPath
   *            Path of ingoing media element
   * @throws KurentoMediaFrameworkException
   *             Exception while sending an SDP answer to client
   */
  @Override
  public void start(String sourceContentPath, String sinkContentPath) {
    try {
      Assert.isTrue(
          sourceContentPath != null || sinkContentPath != null,
          "Cannot invoke start specifying null source and sink content paths",
          1); // TODO

      goToState(
          STATE.STARTING,
          "Cannot start SdpEndPoint in state "
              + getState()
              + ". This is probably due to an explicit session termination comming from another thread",
          1); // TODO

      internalStart(sourceContentPath, sinkContentPath);

    } catch (KurentoMediaFrameworkException ke) {
      internalTerminateWithError(null, ke.getCode(), ke.getMessage(),
          null);
      throw ke;
    } catch (Throwable t) {
      KurentoMediaFrameworkException kmfe = new KurentoMediaFrameworkException(
          t.getMessage(), t, 20029);
      internalTerminateWithError(null, kmfe.getCode(), kmfe.getMessage(),
          null);
      throw kmfe;
    }
  }

  @Override
  public void start(RepositoryItem sourceRepositoryItem,
      RepositoryItem sinkRepositoryItem) {
    try {
      Assert.isTrue(
          sourceRepositoryItem != null || sinkRepositoryItem != null,
          "Cannot invoke start specifying null source and sink content paths",
          1); // TODO

      goToState(
          STATE.STARTING,
          "Cannot start SdpEndPoint in state "
              + getState()
              + ". This is probably due to an explicit session termination comming from another thread",
          1); // TODO

      if (sourceRepositoryItem != null) {
        repositoryHttpPlayer = sourceRepositoryItem
            .createRepositoryHttpPlayer();
      }

      if (sinkRepositoryItem != null) {
        repositoryHttpRecorder = sinkRepositoryItem
            .createRepositoryHttpRecorder();
      }

      String sourceContentPath = sourceRepositoryItem == null ? null
          : repositoryHttpPlayer.getURL();
      String sinkContentPath = sinkRepositoryItem == null ? null
          : repositoryHttpRecorder.getURL();

      internalStart(sourceContentPath, sinkContentPath);

    } catch (KurentoMediaFrameworkException ke) {
      internalTerminateWithError(null, ke.getCode(), ke.getMessage(),
          null);
      throw ke;
    } catch (Throwable t) {
      KurentoMediaFrameworkException kmfe = new KurentoMediaFrameworkException(
          t.getMessage(), t, 20029);
      internalTerminateWithError(null, kmfe.getCode(), kmfe.getMessage(),
          null);
      throw kmfe;
    }
  }

  private void internalStart(String sourceContentPath, String sinkContentPath) {
    MediaPipeline mediaPipeline = createMediaPipeline();
    PlayerEndpoint playerEndpoint = null;
    if (sourceContentPath != null) {
      playerEndpoint = createSourceEndpoint(mediaPipeline,
          sourceContentPath);
    }

    RecorderEndpoint recorderEndpoint = null;
    if (sinkContentPath != null) {
      recorderEndpoint = createSinkEndpoint(mediaPipeline,
          sinkContentPath);
    }

    SdpEndpoint sdpEndpoint = buildAndConnectSdpEndpoint(mediaPipeline,
        playerEndpoint, recorderEndpoint);

    if (playerEndpoint != null)
      playerEndpoint.play();

    if (recorderEndpoint != null)
      recorderEndpoint.record();

    activateMedia(sdpEndpoint, null); // TODO. Ask Jose if
                      // playerEndpoint.play() can be
                      // in the Runnable
  }

  protected void internalStart(SdpEndpoint sdpEndpoint) {
    try {
      releaseOnTerminate(sdpEndpoint);
      Assert.isTrue(sdpEndpoint != null,
          "Cannot invoke start specifying null endPoint", 1); // TODO

      goToState(
          STATE.STARTING,
          "Cannot start SdpEndPoint in state "
              + getState()
              + ". This is probably due to an explicit session termination comming from another thread",
          1); // TODO

      activateMedia(sdpEndpoint, null);

    } catch (KurentoMediaFrameworkException ke) {
      internalTerminateWithError(null, ke.getCode(), ke.getMessage(),
          null);
      throw ke;
    } catch (Throwable t) {
      KurentoMediaFrameworkException kmfe = new KurentoMediaFrameworkException(
          t.getMessage(), t, 20029);
      internalTerminateWithError(null, kmfe.getCode(), kmfe.getMessage(),
          null);
      throw kmfe;
    }

  }

  private MediaPipeline createMediaPipeline() {
    getLogger().info("Creating media pipeline ...");
    MediaPipeline mediaPipeline = mediaPipelineFactory.create();
    releaseOnTerminate(mediaPipeline);
    return mediaPipeline;
  }

  private PlayerEndpoint createSourceEndpoint(MediaPipeline mediaPipeline,
      String contentPath) {
    getLogger().info("Creating PlayerEndpoint ...");
    PlayerEndpoint playerEndpoint = mediaPipeline.newPlayerEndpoint(
        contentPath).build();
    return playerEndpoint;
  }

  private RecorderEndpoint createSinkEndpoint(MediaPipeline mediaPipeline,
      String contentPath) {
    getLogger().info("Creating RecorderEndpoint ...");
    RecorderEndpoint recorderEndpoint = mediaPipeline.newRecorderEndpoint(
        contentPath).build();
    return recorderEndpoint;
  }

  private void activateMedia(SdpEndpoint sdpEndpoint,
      final Runnable runOnContentStart) {

    // Manage fatal errors in pipeline
    sdpEndpoint.getMediaPipeline().addErrorListener(
        new MediaEventListener<ErrorEvent>() {

          @Override
          public void onEvent(ErrorEvent error) {
            getLogger().error(error.getDescription()); // TODO
            internalTerminateWithError(null, error.getErrorCode(),
                error.getDescription(), null);
          }
        });

    // Invoke handler when content start
    sdpEndpoint
        .addMediaSessionStartedListener(new MediaEventListener<MediaSessionStartedEvent>() {

          @Override
          public void onEvent(MediaSessionStartedEvent event) {
            callOnContentStartedOnHanlder();
            if (runOnContentStart != null)
              runOnContentStart.run();
          }
        });

    // Manage end of media session
    sdpEndpoint
        .addMediaSessionTerminatedListener(new MediaEventListener<MediaSessionTerminatedEvent>() {

          @Override
          public void onEvent(MediaSessionTerminatedEvent event) {
            internalTerminateWithoutError(null, 1, "TODO", null);// TODO

          }
        });

    String answerSdp = sdpEndpoint.processOffer(initialJsonRequest
        .getParams().getSdp());
    getLogger().info("Answer SDP: " + answerSdp);
    Assert.notNull(answerSdp,
        "Received invalid null SDP from media server ... aborting",
        20027);
    Assert.isTrue(answerSdp.length() > 0,
        "Received invalid empty SDP from media server ... aborting",
        20028);

    goToState(
        STATE.ACTIVE,
        "Cannot start session in sate "
            + getState()
            + ". This is probably due to an explicit termination of the session from a different threaad",
        1);
    protocolManager.sendJsonAnswer(initialAsyncCtx, JsonRpcResponse
        .newStartSdpResponse(answerSdp, sessionId,
            initialJsonRequest.getId()));
    initialAsyncCtx = null;
    initialJsonRequest = null;
  }

  private SdpEndpoint buildAndConnectSdpEndpoint(MediaPipeline mediaPipeline,
      MediaElement sourceElement, MediaElement sinkElement) {

    getLogger().info("Creating SdpEndpoint ...");
    SdpEndpoint sdpEndpoint = buildSdpEndpoint(mediaPipeline);
    releaseOnTerminate(sdpEndpoint);

    // If no source is provided, jut loopback for having some media back
    // to the client
    if (sourceElement == null) {
      sourceElement = sdpEndpoint; // This produces a loopback.
    }

    getLogger().info("Connecting media pads ...");
    // TODO: should we double check constraints?
    if (sinkElement != null) {
      sdpEndpoint.connect(sinkElement);
    }

    if (sourceElement != null) {
      sourceElement.connect(sdpEndpoint);
    }

    return sdpEndpoint;
  }

  @Override
  protected synchronized void destroy() {
    super.destroy();

    if (repositoryHttpPlayer != null) {
      repositoryHttpPlayer.stop();
      repositoryHttpPlayer = null;
    }

    if (repositoryHttpRecorder != null) {
      repositoryHttpRecorder.stop();
      repositoryHttpRecorder = null;
    }

  }
}
TOP

Related Classes of com.kurento.kmf.content.internal.base.AbstractSdpContentSession

TOP
Copyright © 2018 www.massapi.com. 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.