com.backendless.Media Maven / Gradle / Ivy
/*
* ********************************************************************************************************************
*
* BACKENDLESS.COM CONFIDENTIAL
*
* ********************************************************************************************************************
*
* Copyright 2012 BACKENDLESS.COM. All Rights Reserved.
*
* NOTICE: All information contained herein is, and remains the property of Backendless.com and its suppliers,
* if any. The intellectual and technical concepts contained herein are proprietary to Backendless.com and its
* suppliers and may be covered by U.S. and Foreign Patents, patents in process, and are protected by trade secret
* or copyright law. Dissemination of this information or reproduction of this material is strictly forbidden
* unless prior written permission is obtained from Backendless.com.
*
* ********************************************************************************************************************
*/
package com.backendless;
import java.io.IOException;
import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import android.content.Context;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnPreparedListener;
import android.view.SurfaceHolder;
import com.backendless.exceptions.BackendlessException;
import com.backendless.media.DisplayOrientation;
import com.backendless.media.Session;
import com.backendless.media.SessionBuilder;
import com.backendless.media.StreamProtocolType;
import com.backendless.media.StreamType;
import com.backendless.media.StreamVideoQuality;
import com.backendless.media.audio.AudioQuality;
import com.backendless.media.gl.SurfaceView;
import com.backendless.media.rtsp.RtspClient;
import com.backendless.media.video.VideoQuality;
public final class Media
{
private final static String WOWZA_SERVER_IP = "media.backendless.com";
private final static String WOWZA_SERVER_LIVE_APP_NAME = "mediaAppLive";
private final static String WOWZA_SERVER_VOD_APP_NAME = "mediaAppVod";
private final static Integer WOWZA_SERVER_PORT = 1935;
private final static String RTSP_PROTOCOL = StreamProtocolType.RTSP.getValue();
private final static String HLS_PROTOCOL = StreamProtocolType.HLS.getValue();
private static final String MEDIA_FILES_LOCATION = "/files/media/";
private static final String HLS_PLAYLIST_CONSTANT = "/playlist.m3u8";
private RtspClient rtspClient;
private Session session;
private MediaPlayer mediaPlayer;
private StreamProtocolType protocolType;
private static final Media instance = new Media();
static Media getInstance()
{
return instance;
}
public void toggleFlash()
{
checkSessionIsNull();
session.toggleFlash();
}
public StreamVideoQuality getStreamQuality()
{
checkSessionIsNull();
VideoQuality videoQuality = session.getVideoTrack().getVideoQuality();
int width = videoQuality.resX;
int height = videoQuality.resY;
int framerate = videoQuality.framerate;
int bitrate = videoQuality.bitrate;
StreamVideoQuality streamQuality = StreamVideoQuality.getFromString( width + "x" + height + ", " + framerate + " fps, " + bitrate
/ 1000 + " Kbps" );
return streamQuality;
}
public void setVideoQuality( StreamVideoQuality streamQuality )
{
checkSessionIsNull();
if( streamQuality == null )
{
return;
}
VideoQuality videoQuality = convertVideoQuality( streamQuality );
session.setVideoQuality( videoQuality );
}
private VideoQuality convertVideoQuality( StreamVideoQuality streamQuality )
{
Pattern pattern = Pattern.compile( "(\\d+)x(\\d+)\\D+(\\d+)\\D+(\\d+)" );
Matcher matcher = pattern.matcher( streamQuality.getValue() );
matcher.find();
int width = Integer.parseInt( matcher.group( 1 ) );
int height = Integer.parseInt( matcher.group( 2 ) );
int framerate = Integer.parseInt( matcher.group( 3 ) );
int bitrate = Integer.parseInt( matcher.group( 4 ) ) * 1000;
VideoQuality videoQuality = new VideoQuality( width, height, framerate, bitrate );
return videoQuality;
}
public void setAudioQuality( int sampleRate, int bitRate )
{
checkSessionIsNull();
session.setAudioQuality( new AudioQuality( sampleRate, bitRate ) );
}
public void switchCamera()
{
checkSessionIsNull();
session.switchCamera();
}
public void startPreview()
{
checkSessionIsNull();
session.startPreview();
}
public void stopPreview()
{
checkSessionIsNull();
session.stopPreview();
}
private void stopClientStream()
{
checkRtspClientIsNull();
rtspClient.stopStream();
}
public void releaseSession()
{
checkSessionIsNull();
session.release();
}
public void releaseClient()
{
checkRtspClientIsNull();
rtspClient.release();
}
public boolean isPublishing()
{
checkRtspClientIsNull();
return rtspClient.isStreaming();
}
public boolean isMediaPlayerBusy()
{
checkPlayerIsNull();
return mediaPlayer.isPlaying();
}
private void checkPlayerIsNull()
{
if( mediaPlayer == null )
{
throw new BackendlessException( "Player client is null. Method configure( .. ) must be invoked" );
}
}
private void checkSessionIsNull()
{
if( session == null )
{
throw new BackendlessException( "Session client is null. Method configure( .. ) must be invoked" );
}
}
private void checkRtspClientIsNull()
{
if( rtspClient == null )
{
throw new BackendlessException( "Streaming client is null. Method configure( .. ) must be invoked" );
}
}
/**
*
* default video quality to 176x144 20fps 500Kbps
* default audio quality to 16 000 sampleRate 272000 bitRate
*
*/
public void configureForPublish( Context context, SurfaceView mSurfaceView, DisplayOrientation orientation )
{
session = getSession( context, mSurfaceView, orientation.getValue() );
rtspClient = getRtspClient( context, session );
}
/**
* StreamProtocolType sets to default value - RTSP
*
* @param mSurfaceHolder
*/
public void configureForPlay( SurfaceHolder mSurfaceHolder )
{
configureForPlay( mSurfaceHolder, StreamProtocolType.RTSP );
}
public void configureForPlay( SurfaceHolder mSurfaceHolder, StreamProtocolType protocolType )
{
this.protocolType = protocolType;
mediaPlayer = new MediaPlayer();
mediaPlayer.setDisplay( mSurfaceHolder );
mediaPlayer.setAudioStreamType( AudioManager.STREAM_MUSIC );
mediaPlayer.setOnPreparedListener( new OnPreparedListener() {
@Override
public void onPrepared( MediaPlayer mp )
{
mp.start();
}
} );
}
public void recordVideo( String tube, String streamName ) throws BackendlessException
{
startRtspStream( tube, streamName, StreamType.LIVE_RECORDING );
}
public void broadcastLiveVideo( String tube, String streamName ) throws BackendlessException
{
startRtspStream( tube, streamName, StreamType.LIVE );
}
public void playLiveVideo( String tube, String streamName ) throws IllegalArgumentException, SecurityException, IllegalStateException,
IOException, BackendlessException
{
playStream( tube, streamName, StreamType.RECORDING );
}
public void playOnDemandVideo( String tube, String streamName ) throws IllegalArgumentException, SecurityException,
IllegalStateException, IOException, BackendlessException
{
playStream( tube, streamName, StreamType.AVAILABLE );
}
private void startRtspStream( String tube, String streamName, StreamType streamType ) throws BackendlessException
{
checkSessionIsNull();
checkRtspClientIsNull();
if( mediaPlayer != null )
{
mediaPlayer.reset();
}
streamName = makeNameValid( streamName );
tube = makeTubeValid( tube );
String operationType = getOperationType( streamType );
String params = getConnectParams( tube, operationType, streamName );
startStream( rtspClient, streamName, params );
}
public void stopPublishing()
{
checkRtspClientIsNull();
if( rtspClient.isStreaming() )
{
stopClientStream();
}
}
private String getOperationType( StreamType streamType )
{
return ( streamType == StreamType.LIVE ) ? "publishLive" : "publishRecorded";
}
private void playStream( String tube, String streamName, StreamType streamType ) throws IllegalArgumentException, SecurityException,
IllegalStateException, IOException, BackendlessException
{
checkPlayerIsNull();
if( mediaPlayer.isPlaying() )
{
throw new BackendlessException( "Other stream is playing now. You must to stop it before" );
}
streamName = makeNameValid( streamName );
tube = makeTubeValid( tube );
if( session != null )
{
session.stopPreview();
}
mediaPlayer.reset();
if( protocolType == null )
{
protocolType = StreamProtocolType.RTSP;
}
String protocol = getProtocol( protocolType );
String operationType = ( streamType == StreamType.RECORDING ) ? "playLive" : "playRecorded";
String wowzaAddress = WOWZA_SERVER_IP + ":" + WOWZA_SERVER_PORT + "/"
+ ( ( streamType == StreamType.RECORDING ) ? WOWZA_SERVER_LIVE_APP_NAME : WOWZA_SERVER_VOD_APP_NAME ) + "/_definst_/";
String params = getConnectParams( tube, operationType, streamName );
String streamPath = getStreamName( streamName, protocolType );
String url = protocol + wowzaAddress + streamPath + params;
mediaPlayer.setDataSource( url );
mediaPlayer.prepareAsync();
}
private String makeTubeValid( String tube )
{
if( tube == null || tube.isEmpty() )
{
tube = "default";
}
else
{
tube = tube.trim();
}
return tube;
}
private String makeNameValid( String streamName )
{
if( streamName == null || streamName.isEmpty() )
{
streamName = "default";
}
else
{
streamName = streamName.trim().replace( '.', '_' );
}
return streamName;
}
public void stopVideoPlayback()
{
checkPlayerIsNull();
if( mediaPlayer.isPlaying() )
{
mediaPlayer.stop();
mediaPlayer.reset();
}
}
private String getStreamName( String fileName, StreamProtocolType protocol )
{
String subDir = Backendless.getApplicationId().toLowerCase() + MEDIA_FILES_LOCATION;
String hlsAdditionalParameter = ( protocol == StreamProtocolType.HLS ) ? HLS_PLAYLIST_CONSTANT : "";
return subDir + fileName + hlsAdditionalParameter;
}
private String getProtocol( StreamProtocolType streamProtocolType )
{
if( streamProtocolType.equals( StreamProtocolType.RTSP ) )
{
return RTSP_PROTOCOL;
}
if( streamProtocolType.equals( StreamProtocolType.HLS ) )
{
return HLS_PROTOCOL;
}
throw new BackendlessException( "Backendless Android SDK not supported protocol type '" + streamProtocolType + "'" );
}
private Session getSession( Context context, SurfaceView mSurfaceView, int orientation )
{
Session mSession = SessionBuilder.getInstance().setContext( context ).setAudioEncoder( SessionBuilder.AUDIO_AAC )
.setVideoEncoder( SessionBuilder.VIDEO_H264 ).setSurfaceView( mSurfaceView ).setPreviewOrientation( orientation )
.setCallback( (Session.Callback) context ).build();
return mSession;
}
private String getConnectParams( String tube, String operationType, String streamName )
{
String paramsToSend;
BackendlessUser currentUser = Backendless.UserService.CurrentUser();
Object identity = currentUser != null ? currentUser.getProperty( "user-token" ) : null;
HashMap map = new HashMap();
map.putAll( HeadersManager.getInstance().getHeaders() );
map.put( "identity", identity != null ? identity.toString() : map.get( "user-token" ) );
paramsToSend = "?application-id=" + map.get( "application-id" ) + "&version=" + Backendless.getVersion() + "&identity="
+ map.get( "identity" ) + "&tube=" + tube + "&operationType=" + operationType + "&streamName=" + streamName;
return paramsToSend;
}
// Connects/disconnects to the RTSP server and starts/stops the stream
private void startStream( RtspClient rtspClient, String streamName, String params ) throws BackendlessException
{
if( rtspClient.isStreaming() )
{
throw new BackendlessException( "Rtsp client is working on other stream" );
}
rtspClient.setServerAddress( WOWZA_SERVER_IP, WOWZA_SERVER_PORT );
rtspClient.setStreamPath( "/" + WOWZA_SERVER_LIVE_APP_NAME + "/" + streamName + params );
rtspClient.startStream();
}
private RtspClient getRtspClient( Context context, Session mSession )
{
// Configures the RTSP client
if( rtspClient == null )
{
rtspClient = new RtspClient();
rtspClient.setSession( mSession );
rtspClient.setCallback( (RtspClient.Callback) context );
}
return rtspClient;
}
public StreamProtocolType getProtocolType()
{
return protocolType;
}
public void setProtocolType( StreamProtocolType protocolType )
{
this.protocolType = protocolType;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy