Skip to main content

RTM Playback

Description and Features

RTMP Playback Component enables application developers to add playback of RTMP live and on demand streams to their apps.

Supported codecs are H.264 Video, AAC and MP3 Audio.

Video streams are decoded and rendered on a Surface that is hold by the application, usually connected to a SurfaceView.

Audio streams are decoded and rendered to system audio using the Android AudioSession/AudioTrack API.

The interface and usage are similar to the Android MediaPlayer. The Android MediaPlayerControl interface is implemented to enable control through an android.widget.MediaController instance.

License

The playback component requires a special feature flag to be enabled in your nanoStream license key. It not necessarily included in nanoStream Android SDK licenses.

Interface

Package name

net.nanocosmos.nanoStream.streamer

Declaration

public abstract class NanostreamPlayer implements MediaPlayercontrol, Surfaceholder.Callback

Function Life Cycle

Instance HandlingInitializationCapabilitiesQueriesPlayback ControlSupported by RTMP Player
createNanostreamPlayer
setSettingsyes
setPlayerEventListeneryes
canPrepareyes
canPrepareAsyncyes
canPauseyes
canSeekBackwardyes
canSeekForwardyes
getStateyes
isPlayingyes
getCurrentPositionno
getDurationno
prepareno
prepareAsyncno
startyes
pauseyes
seekToyes
stopyes
startyes
stopyes
closeno
releaseyes

Creating an Instance

NanostreamPlayer instances can be created through the static factory function createNanostreamPlayer at the top level nanoStream class. NanostreamPlayer is designed to support multiple player instances. The number of parallel instances can be limited by system resources such as codec,surfaces,memory, network connections and bandwidth.

Configuration and Settings

Initial player settings are wrapped by the NanostreamPlayer.PlayerSettings class. The settings can be applied by calling NanostreamPlayer.setSettings.

PlayerSettings:

SettingFunctionsDescriptionTypeDefault Values
LicensegetLicense/setLicensenanoStream license keyStringempty
UrlgetUrl/setUrlRTMP urlStringempty
Stream NamegetStreamname/setStreamnameRTMP stream nameStringempty
User NamegetUsername/setUsernameUser name if RTMP authentication is requiredStringempty
PasswordgetPassword/setPassword Password if RTMP authentication is requiredStringempty
Buffer TimegetBufferTimeMs/setBufferTimeMsLength of the stream buffer in millisecondsInteger2000ms/2s
Frame Dropping ModegetFrameDroppingMode/setFrameDroppingModeConfiguration of the dropping mode regarding different droppable frame typesFrameDroppingModeDROP_NO_FRAMES
Stream PlaybackgetVideoPlayback/getAudioPlayback/setStreamPlaybackEnable stream types to be decoded and playedbooleanvideo:true, audio:true
TrackTimoutgetTrackTimeout/setTrackTimeoutTimeout to waiting for Track infolong10000
EndlessModegetEndlessMode/setEndlessModeReopen the stream until stop callbooleanfalse

Player State

The player stat can be queried through the getState() function

/**
*
* The different states of the player instance.
*
*/
public enum PlayerState
{
IDLE, INITIALIZED, PREPARED, STARTED, PAUSED, SEEKING, BUFFERING, RECONNECTING, PLAYBACKCOMPLETED, STOPPING, STOPPED;
}
StateDescriptionSupported by RTMP Player
PlayerState.IDLEInitial state. Player has not yet been initialized or has been closed.yes
PlayerState.INITIALIZEDPlayer has been initialized with license and settings.yes
PlayerState.PREPAREDPlayer has been prepared and is ready to start.no
PlayerState.STARTEDPlayback has been started.yes
PlayerState.PAUSEDPlayback has been paused.yes
PlayerState.SEEKINGPlayer is Seekingyes
PlayerState.BUFFERINGPlayer is buffering stream data.yes
PlayerState.RECONNECTINGPlayer is performing a reconnectno
PlayerState.PLAYBACKCOMPLETEDPlayback has ended due to end of stream.yes
PlayerState.STOPPINGPlayer is stoppingyes
PlayerState.STOPPEDPlayer is stoppedyes

Event Notification

Event notifications can be received through the NanostreamPlayer.PlayerEventListener interface. Derive your listener from this interface and add it to the player by calling setPlayerEventListener().

Status Events

Event Type : TYPE_RTMP_STATUS

Event CodeDescriptionCorresponding State
NanostreamEvent.CODE_STREAM_STARTEDPlayback has been started.PlayerState.STARTED
NanostreamEvent.CODE_STREAM_STOPPINGPlayback will stop.PlayerState.STOPPING
NanostreamEvent.CODE_STREAM_STOPPEDPlayback has been stopped.PlayerState.STOPPED
NanostreamEvent.CODE_STREAM_ERROR_CONNECTThe connect to the stream url failed.PlayerState.STOPPED
NanostreamEvent.CODE_STREAM_BUFFERINGPlayer is buffering stream dataPlayerState.BUFFERING
NanostreamEvent.CODE_STREAM_PLAYBACKCOMPLETEDPlayback has ended due to end of stream.PlayerState.PLAYBACKCOMPLETED
NanostreamEvent.CODE_STREAM_NOT_FOUNDThe specified stream could not be found.PlayerState.STOPPED
NanostreamEvent.CODE_STREAM_SEEKINGThe Stream is seeking.PlayerState.SEEKING
NanostreamEvent.CODE_STREAM_PAUSEDThe Stream is pausedPlayerState.PAUSED
NanostreamEvent.CODE_STREAM_VIDEO_FORMAT_AVAILABLEThe Stream has a MediaFormat for the Video Track
NanostreamEvent.CODE_STREAM_AUDIO_FORMAT_AVAILABLEThe Stream has a MediaFormat for the Audio Track

Results and Error Events

Event Type : TYPENANORESULTS Event Codes : Values of type nanoResults

Event CodeDescriptionCorresponding State
nanoResults.N_NOT_INITIALIZEDThe RTMP library has not been initialized properly.PlayerState.STOPPED
nanoResults.N_ALLOCATEDATA_FAILED_RTMP_SRCMemory allocation failed.PlayerState.STOPPED
nanoResults.N_LICENSE_INVALIDLicense check failed - License invalid.PlayerState.STOPPED
nanoResults.N_LICENSE_INVALID_RTMP_SRCLicense check failed - RTMP playback is not included.PlayerState.STOPPED
nanoResults.N_LICENSE_EXPIREDLicense check failed - The license period has ended.PlayerState.STOPPED
nanoResults.N_TCP_CONNECT_FAILEDTCP connect failed.PlayerState.STOPPED
nanoResults.N_RTMP_HANDSHAKE_FAILEDRTMP handshake failed.PlayerState.STOPPED
nanoResults.N_RTMP_CONNECT_FAILEDRTMP connect failed.PlayerState.STOPPED
nanoResults.N_RTMP_AUTH_FAILEDRTMP authentication is required and failed.PlayerState.STOPPED
nanoResults.N_RTMP_APP_INVALIDThe application part of the url is invalid and has been rejected.PlayerState.STOPPED
nanoResults.N_RTMP_STATUS_PLAY_STREAM_NOT_FOUNDThe stream name could not be found.PlayerState.STOPPED
nanoResults.N_RTMP_STATUS_PLAY_STREAM_SEEKThe player is seeking.PlayerState.SEEKING
nanoResults.N_RTMP_SEEK_NOT_AVAILABLEThe stream can not seek.
nanoResults.N_RTMP_SEEK_FAILEDThe stream can not seek.

Audio / Video Format

After the NanostreamEvent.CODE_STREAM_AUDIO/VIDEO_FORMAT_AVAILABLE event, you can get the MediaFormat Object with the getAudio/VideoFormat()(2) function call. We added two custom Fields for the Video MediaFormat:     NanostreamPlayer.KEY_ASPECT_RATIO_WIDTH     NanostreamPlayer.KEY_ASPECT_RATIO_HEIGHT With these custom fields you can get the aspect ratio width and height.

MediaFormat videoFormat = mPlayer.getVideoFormat();

int aspectRatioWidth = videoFormat.getInteger(NanostreamPlayer.KEY_ASPECT_RATIO_WIDTH);
int aspectRatioHeight = videoFormat.getInteger(NanostreamPlayer.KEY_ASPECT_RATIO_HEIGHT);

Implementation Example

public class PlayerActivity extends Activity implements PlayerEventListener, SurfaceHolder.Callback {
...
private NanostreamPlayer mPlayer = null;
private String license = "YOUR LICENSE CODE";

private String strStreamUrl = "rtmp://192.168.1.100/vod";
private String strStreamname = "mp4:file.mp4";

private LinearLayout root;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
root = new LinearLayout(this);
root.setOrientation(LinearLayout.VERTICAL);
root.setLayoutParams(containerParams);
root.setBackgroundColor(Color.BLACK);

...

mPlayer = nanoStream.createNanostreamPlayer();

PlayerSettings settings = mPlayer.new PlayerSettings();

settings.setLicense(license);
settings.setUrl(strStreamUrl);
settings.setStreamname(strStreamname);
settings.setAuthUsername("");
settings.setAuthPassword("");
settings.setBufferTimeMs(2000);

mPlayer.setSettings(settings);
mPlayer.setPlayerEventListener(this);

...
// we need a surface Callback for the application
LinearLayout.LayoutParams surfaceParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT, 0.5F);
surfaceParams.gravity = Gravity.CENTER;
surfaceParams.weight = 0.5f;

SurfaceView surfaceView = new SurfaceView(this);
surfaceView.setLayoutParams(surfaceParams);
surfaceView.getHolder.addCallback(this);

root.addView(surfaceView);
setContentView(root);
}

...

@Override
public void onPlayerEvent(NanostreamEvent event, NanostreamPlayer instance) {
final String msg = event.GetDescription();
Log.d(this.getClass().getName(), event.GetDescription());
}

@Override
public void surfaceCreated(SurfaceHolder holder) {
mPlayer.surfaceCreated(holder);

try {
if (!mPlayer.getState().equals(PlayerState.STARTED)) {
mPlayer.start();
}
} catch (IllegalStateException e) {
e.printStackTrace();
}
}

@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
mPlayer.surfaceChanged(holder, format, width, height);
}

@Override
public void surfaceDestroyed(SurfaceHolder holder) {
mPlayer.surfaceDestroyed(holder);
}
}