Aller au contenu

Player HLS (Http Live Streaming) sur tablette


broadpeak

Recommended Posts

Bonjour,

J'ai les codes source d'une application lisant le .mp4 sur un serveur Wamp et wowza qui tourne sur ma machine. L'application tourne sur Galaxy Tab 10.1 en version 3.2 d'Android. Je veux que cette application puisse lire les fichier HLS (Http Live Streaming) qui sont au format .m3u8.

J'ai lu sur le net que le HLS est lisible nativement depuis la version 3.0 mais ne réussissant pas à le lire avec l'application, j'ai opté pour la librairie Vitamio qui permet de lire ce format de stream à partir d'Android 2.1.

Voici mon code source de l'activité où le Player est appelé :

package fr.niji.broadpeak.activity;

import java.io.File;

import java.io.UnsupportedEncodingException;

import java.util.ArrayList;

import android.app.Activity;

import android.content.Context;

import android.content.Intent;

/*import android.media.AudioManager;

import android.media.MediaPlayer;

import android.media.MediaPlayer.OnBufferingUpdateListener;

import android.media.MediaPlayer.OnCompletionListener;

import android.media.MediaPlayer.OnErrorListener;

import android.media.MediaPlayer.OnPreparedListener;

import android.media.MediaPlayer.OnVideoSizeChangedListener;*/

import io.vov.vitamio.MediaPlayer;

import io.vov.vitamio.MediaPlayer.OnBufferingUpdateListener;

import io.vov.vitamio.MediaPlayer.OnCompletionListener;

import io.vov.vitamio.MediaPlayer.OnErrorListener;

import io.vov.vitamio.MediaPlayer.OnPreparedListener;

import io.vov.vitamio.MediaPlayer.OnVideoSizeChangedListener;

import io.vov.vitamio.VitamioInstaller;

import io.vov.vitamio.widget.MediaController;

import io.vov.vitamio.widget.VideoView;

import android.os.Bundle;

import android.os.Handler;

import android.os.PowerManager;

import android.os.PowerManager.WakeLock;

import android.util.Log;

import android.view.SurfaceHolder;

import android.view.SurfaceView;

//import io.vov.vitamio.widget.VideoView;

import android.view.View;

import android.view.SurfaceHolder.Callback;

import android.view.View.OnClickListener;

import android.widget.ImageButton;

import android.widget.RelativeLayout;

import android.widget.SeekBar;

import android.widget.TextView;

import android.widget.Toast;

import android.widget.SeekBar.OnSeekBarChangeListener;

import fr.niji.broadpeak.R;

import fr.niji.broadpeak.dataproxy.service.BroadpeakDataManager;

import fr.niji.broadpeak.dataproxy.webservice.getsessionurl.GetSessionUrl;

import fr.niji.broadpeak.util.Config;

import fr.niji.broadpeak.util.Resources;

import fr.niji.broadpeak.util.TimeUtils;

import fr.niji.lib.dataproxy.model.ResponseBusinessObject;

import fr.niji.lib.dataproxy.service.DataManager.OnDataListener;

import fr.niji.lib.dataproxy.service.model.BusinessResponse;

public class BroadpeakDemoPlayer extends Activity implements OnClickListener, OnPreparedListener, OnErrorListener,

OnVideoSizeChangedListener, Callback, OnSeekBarChangeListener, OnCompletionListener, OnDataListener, OnBufferingUpdateListener{

private static final String LOG_TAG = BroadpeakDemoPlayer.class.getSimpleName();

public static final String PLAYER_FILE_PATH = "playerLivePath";

public static final String PLAYER_FILE_ID = "playerFileId";

public static final String PLAYER_TYPE = "playerType";

public static final String PLAYER_RESUME_POSITION = "playerResumePosition";

public static final int TYPE_VOD_CONNECTED = 1;

public static final int TYPE_VOD_EMULATED = 2;

public static final int TYPE_LIVE_CONNECTED = 3;

public static final int TYPE_LIVE_EMULATED = 4;

private static final int DELTA_RW_FW = 5000;

private static final int DELTA_LIVE = 30000;

private static final int PROGRESS_BAR_UPDATE_DELAY = 1500;

private SurfaceView mSurfaceView;

//private SurfaceView mSurfaceView;

private SurfaceHolder mSurfaceHolder;

private MediaPlayer mMediaPlayer;

//VitamioInstaller vitamioInstaller;

private int mPlayerType;

private int mCurrentBufferPercentage;

private String mFilePath;

private String mFileId;

private int mResumePosition;

int percentBuffer;

private Toast mToast;

private WakeLock mWakeLock;

private int mTerminalType;

private String mUserId;

private long mLastPosition;

private RelativeLayout mLayoutControls;

private boolean mIsLayoutControlsVisible = true;

private SeekBar mSeekBar;

private TextView mTextViewCurrentTime;

private TextView mTextViewFullTime;

private ImageButton mButtonStartOver;

private ImageButton mButtonPlay;

private ImageButton mButtonPause;

private ImageButton mButtonRewind;

private ImageButton mButtonForward;

private ImageButton mButtonLive;

private boolean mIsButtonLiveEnabled = true;

private boolean mIsVideoReadyToBePlayed = false;

private boolean mIsVideoDimensionsKnown = false;

private int mVideoHeight = 0;

private int mVideoWidth = 0;

private long mVideoLength = -1;

private int mRequestId = -1;

private Runnable mRunnableProgressBarUpdate;

private Handler mHandler = new Handler();

private BroadpeakDataManager mDataManager;

private String mErrorGettingVideo;

private String mErrorPlayingVideo;

@Override

public void onCreate(final Bundle bundle) {

super.onCreate(bundle);

Intent intent = getIntent();

mDataManager = BroadpeakDataManager.getInstance(this);

mErrorGettingVideo = getString(R.string.error_getting_video_url);

mErrorPlayingVideo = getString(R.string.error_playing_video);

if (intent != null) {

mPlayerType = intent.getIntExtra(PLAYER_TYPE, 0);

mFilePath = intent.getStringExtra(PLAYER_FILE_PATH);

mFileId = intent.getStringExtra(PLAYER_FILE_ID);

if (Config.SHOW_LOG) {

Log.d(LOG_TAG, "mFilePath: " + mFilePath);

Log.d(LOG_TAG, "mFileId: " + mFileId);

}

mResumePosition = intent.getIntExtra(PLAYER_RESUME_POSITION, 0);

// must retrieve url ?

if (mFilePath == null || mFilePath.length() == 0) {

try {

mRequestId = mDataManager.getSessionUrl(this, mFileId, Resources.getInstance().mUserId);

mDataManager.addOnDataListener(mRequestId, this);

} catch (final UnsupportedEncodingException e) {

e.printStackTrace();

}

}

}

setContentView(R.layout.player);

// Decalage a 30s pour le live emulated

if (mPlayerType == TYPE_LIVE_EMULATED) {

mResumePosition = Config.LIVE_DEFAULT_OFFSET;

}

// Player management

//mSurfaceView = (SurfaceView) findViewById(R.id.surface_live);

mSurfaceView = (SurfaceView) findViewById(R.id.surface_live);

mSurfaceView.setOnClickListener(this);

mSurfaceHolder = mSurfaceView.getHolder();

mSurfaceHolder.addCallback(this);

mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

// Controls management

mLayoutControls = (RelativeLayout) findViewById(R.id.player_controls);

mLayoutControls.setClickable(true);

mSeekBar = (SeekBar) findViewById(R.id.seek_bar);

mSeekBar.setOnSeekBarChangeListener(this);

mTextViewCurrentTime = (TextView) findViewById(R.id.textview_current_time);

mTextViewFullTime = (TextView) findViewById(R.id.textview_full_time);

mButtonStartOver = (ImageButton) findViewById(R.id.btn_startover);

mButtonStartOver.setOnClickListener(this);

mButtonPlay = (ImageButton) findViewById(R.id.btn_play);

mButtonPlay.setOnClickListener(this);

mButtonPause = (ImageButton) findViewById(R.id.btn_pause);

mButtonPause.setOnClickListener(this);

mButtonRewind = (ImageButton) findViewById(R.id.btn_rw);

mButtonRewind.setOnClickListener(this);

mButtonForward = (ImageButton) findViewById(R.id.btn_fw);

mButtonForward.setOnClickListener(this);

mButtonLive = (ImageButton) findViewById(R.id.btn_live);

mButtonLive.setOnClickListener(this);

Resources resources = Resources.getInstance();

mTerminalType = resources.mTerminalType;

mUserId = resources.mUserId;

// Player type management

switch (mPlayerType) {

case TYPE_LIVE_CONNECTED:

mLayoutControls.setVisibility(View.GONE);

mIsLayoutControlsVisible = false;

break;

case TYPE_LIVE_EMULATED:

mSeekBar.setVisibility(View.GONE);

mTextViewCurrentTime.setVisibility(View.GONE);

mTextViewFullTime.setVisibility(View.GONE);

break;

case TYPE_VOD_CONNECTED:

mButtonStartOver.setVisibility(View.GONE);

mButtonLive.setVisibility(View.GONE);

break;

case TYPE_VOD_EMULATED:

mButtonStartOver.setVisibility(View.GONE);

mButtonLive.setVisibility(View.GONE);

break;

}

mRunnableProgressBarUpdate = new Runnable() {

public void run() {

mHandler.removeCallbacks(mRunnableProgressBarUpdate);

int progress = -1;

if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {

if (mVideoLength > 0) {

final long currentPosition = mMediaPlayer.getCurrentPosition();

progress = (int) Math.floor(currentPosition / (float) mVideoLength * 100);

mSeekBar.setProgress(progress);

mTextViewCurrentTime.setText(TimeUtils.formatDuration(currentPosition / 1000));

} else {

progress = 0;

mSeekBar.setProgress(progress);

mTextViewCurrentTime.setText("");

}

}

mHandler.postDelayed(mRunnableProgressBarUpdate, PROGRESS_BAR_UPDATE_DELAY);

}

};

}

@Override

protected void onResume() {

super.onResume();

acquireWakeLock();

}

@Override

protected void onPause() {

super.onPause();

releaseMediaPlayer();

doCleanUp();

releaseWakeLock();

}

@Override

protected void onStop() {

super.onStop();

if (mPlayerType == TYPE_VOD_CONNECTED) {

try {

BroadpeakDataManager.getInstance(this).retrieveSetLastPlay(BroadpeakDataManager.TYPE_NETWORK, null,

mTerminalType, mUserId, mFileId, mLastPosition, -1);

} catch (UnsupportedEncodingException e) {

Log.e(LOG_TAG, "Error while calling setLastPlay", e);

}

}

}

@Override

protected void onDestroy() {

super.onDestroy();

releaseMediaPlayer();

doCleanUp();

}

public void surfaceChanged(final SurfaceHolder holder, final int format, final int width, final int height) {

Log.d(LOG_TAG, "surfaceChanged called");

}

public void surfaceDestroyed(final SurfaceHolder holder) {

Log.d(LOG_TAG, "surfaceDestroyed called");

}

public void surfaceCreated(final SurfaceHolder holder) {

Log.d(LOG_TAG, "surfaceCreated called");

if (mFilePath != null) {

playVideo();

}

}

public void onClick(final View view) {

if (view == mSurfaceView) {

if (mPlayerType != TYPE_LIVE_CONNECTED) {

mLayoutControls.setVisibility(mIsLayoutControlsVisible ? View.GONE : View.VISIBLE);

mIsLayoutControlsVisible = !mIsLayoutControlsVisible;

}

} else if (view == mButtonPlay) {

pressPlayButton();

} else if (view == mButtonPause) {

pressPauseButton();

} else if (view == mButtonRewind) {

if (mPlayerType == TYPE_LIVE_CONNECTED || mPlayerType == TYPE_LIVE_EMULATED) {

mButtonLive.setEnabled(true);

mButtonForward.setEnabled(true);

mIsButtonLiveEnabled = true;

}

try {

if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {

mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() - DELTA_RW_FW);

}

} catch (Exception e) {

Log.e(LOG_TAG, "An error occurred", e);

}

} else if (view == mButtonForward) {

if (mPlayerType == TYPE_LIVE_CONNECTED || mPlayerType == TYPE_LIVE_EMULATED) {

mButtonStartOver.setEnabled(true);

}

try {

if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {

mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() + DELTA_RW_FW);

}

} catch (Exception e) {

Log.e(LOG_TAG, "An error occurred", e);

}

} else if (view == mButtonLive) {

mButtonForward.setEnabled(false);

mButtonLive.setEnabled(false);

mIsButtonLiveEnabled = false;

mButtonStartOver.setEnabled(true);

try {

if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {

mMediaPlayer.seekTo(mMediaPlayer.getCurrentPosition() + DELTA_LIVE);

}

} catch (Exception e) {

Log.e(LOG_TAG, "An error occurred", e);

}

} else if (view == mButtonStartOver) {

mButtonLive.setEnabled(true);

mButtonForward.setEnabled(true);

mIsButtonLiveEnabled = true;

try {

if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {

mMediaPlayer.seekTo(0);

}

} catch (Exception e) {

Log.e(LOG_TAG, "An error occurred", e);

}

}

}

private void pressPauseButton() {

mButtonPlay.setVisibility(View.VISIBLE);

mButtonPause.setVisibility(View.GONE);

mButtonForward.setEnabled(false);

mButtonRewind.setEnabled(false);

if (mPlayerType == TYPE_LIVE_CONNECTED || mPlayerType == TYPE_LIVE_EMULATED) {

mButtonLive.setEnabled(false);

mButtonStartOver.setEnabled(false);

}

try {

if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {

mMediaPlayer.pause();

}

} catch (Exception e) {

Log.e(LOG_TAG, "An error occurred", e);

}

}

private void pressPlayButton() {

mButtonPlay.setVisibility(View.GONE);

mButtonPause.setVisibility(View.VISIBLE);

if (mPlayerType == TYPE_LIVE_CONNECTED || mPlayerType == TYPE_LIVE_EMULATED) {

if (mIsButtonLiveEnabled) {

mButtonLive.setEnabled(true);

mButtonForward.setEnabled(true);

}

mButtonRewind.setEnabled(true);

mButtonStartOver.setEnabled(true);

} else {

mButtonRewind.setEnabled(true);

mButtonForward.setEnabled(true);

}

try {

if (mMediaPlayer != null && !mMediaPlayer.isPlaying()) {

mMediaPlayer.start();

}

} catch (Exception e) {

Log.e(LOG_TAG, "An error occurred", e);

}

}

private void playVideo() {

doCleanUp();

try {

// Create a new media player and set the listeners

/*mMediaPlayer = new MediaPlayer();

mMediaPlayer.setDataSource(mFilePath);

mMediaPlayer.setLooping(mPlayerType == TYPE_LIVE_CONNECTED || mPlayerType == TYPE_LIVE_EMULATED);

mMediaPlayer.setDisplay(mSurfaceHolder);

mMediaPlayer.prepare();

mMediaPlayer.seekTo(mResumePosition);

mMediaPlayer.setOnPreparedListener(this);

mMediaPlayer.setOnVideoSizeChangedListener(this);

mMediaPlayer.setOnCompletionListener(this);

mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);*/

mMediaPlayer = new MediaPlayer(this);

mMediaPlayer.setDataSource(mFilePath);

mMediaPlayer.setDisplay(mSurfaceHolder);

mMediaPlayer.prepare();

mMediaPlayer.seekTo(mResumePosition);

mMediaPlayer.setScreenOnWhilePlaying(true);

mMediaPlayer.setOnBufferingUpdateListener(this);

mMediaPlayer.setOnCompletionListener(this);

//mMediaPlayer.setAudioTrack(AudioManager.STREAM_MUSIC);

mMediaPlayer.setOnPreparedListener(this);

mMediaPlayer.setOnVideoSizeChangedListener(this);

} catch (Exception e) {

Log.e(LOG_TAG, "error: " + e.getMessage(), e);

showErrorMessage(mErrorPlayingVideo);

// Toast.makeText(this, "Impossible de jouer la vidéo",

// 5000).show();

}

}

private void releaseMediaPlayer() {

if (mMediaPlayer != null) {

mLastPosition = mMediaPlayer.getCurrentPosition() / 1000;

mMediaPlayer.release();

mMediaPlayer = null;

}

}

private void doCleanUp() {

mVideoWidth = 0;

mVideoHeight = 0;

mVideoLength = -1;

mIsVideoReadyToBePlayed = false;

mIsVideoDimensionsKnown = false;

mHandler.removeCallbacks(mRunnableProgressBarUpdate);

}

private void acquireWakeLock() {

PowerManager.WakeLock wl = mWakeLock;

if (wl == null) {

PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);

wl = mWakeLock = pm.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, LOG_TAG);

}

if (!wl.isHeld()) {

wl.acquire();

Log.d(LOG_TAG, "acquire wakelock");

}

}

private void releaseWakeLock() {

PowerManager.WakeLock wl = mWakeLock;

if (wl != null) {

if (wl.isHeld()) {

wl.release();

Log.d(LOG_TAG, "release wakelock");

}

}

}

private void showErrorMessage(final String string) {

if (mToast != null) {

mToast.cancel();

mToast.setText(string);

} else {

mToast = Toast.makeText(this, string, Toast.LENGTH_LONG);

}

mToast.show();

}

private void startVideoPlayback() {

Log.d(LOG_TAG, "startReading: width " + mVideoWidth + " height " + mVideoHeight);

mSurfaceHolder.setFixedSize(mVideoWidth, mVideoHeight);

mVideoLength = mMediaPlayer.getDuration();

mTextViewFullTime.setText(TimeUtils.formatDuration(mVideoLength / 1000));

mMediaPlayer.start();

if (mPlayerType == TYPE_VOD_CONNECTED || mPlayerType == TYPE_VOD_EMULATED) {

mHandler.post(mRunnableProgressBarUpdate);

}

}

public void onPrepared(final MediaPlayer mediaPlayer) {

Log.d(LOG_TAG, "onPrepared");

mIsVideoReadyToBePlayed = true;

if (mIsVideoReadyToBePlayed && mIsVideoDimensionsKnown) {

startVideoPlayback();

}

}

public void onVideoSizeChanged(final MediaPlayer mediaPlayer, final int width, final int height) {

Log.d(LOG_TAG, "OnVideoSizeChanged");

if (width > 0 && height > 0) {

mVideoHeight = height;

mVideoWidth = width;

mIsVideoDimensionsKnown = true;

if (mIsVideoReadyToBePlayed && mIsVideoDimensionsKnown) {

startVideoPlayback();

}

}

}

public boolean onError(final MediaPlayer mediaPlayer, final int what, final int extra) {

doCleanUp();

showErrorMessage("An error occurred");

return false;

}

public void onProgressChanged(final SeekBar seekBar, final int progress, final boolean fromUser) {

if (fromUser) {

if (mVideoLength > 0) {

final int currentPosition = ((int) Math.floor(progress / 100f * mVideoLength)) / 1000;

mTextViewCurrentTime.setText(TimeUtils.formatDuration(currentPosition));

} else {

mTextViewCurrentTime.setText("");

}

}

}

public void onStartTrackingTouch(final SeekBar seekBar) {

if (mPlayerType == TYPE_VOD_CONNECTED || mPlayerType == TYPE_VOD_EMULATED) {

mHandler.removeCallbacks(mRunnableProgressBarUpdate);

}

pressPauseButton();

}

public void onStopTrackingTouch(final SeekBar seekBar) {

if (mPlayerType == TYPE_VOD_CONNECTED || mPlayerType == TYPE_VOD_EMULATED) {

mHandler.post(mRunnableProgressBarUpdate);

}

final int currentPosition = (int) Math.floor(mSeekBar.getProgress() / 100f * mVideoLength);

try {

if (mMediaPlayer != null) {

mMediaPlayer.seekTo(currentPosition);

}

} catch (Exception e) {

Log.e(LOG_TAG, "An error occurred", e);

}

pressPlayButton();

}

public void onCompletion(final MediaPlayer mediaPlayer) {

mMediaPlayer.seekTo(0);

mSeekBar.setProgress(0);

mTextViewCurrentTime.setText(TimeUtils.formatDuration(0));

mButtonPlay.setVisibility(View.VISIBLE);

mButtonPause.setVisibility(View.GONE);

}

public void onCacheRequestFinished(ResponseBusinessObject response) {

}

public void onDataFromDatabase(int code, ArrayList<?> data) {

}

public void onRequestFinished(int requestId, boolean suceed, BusinessResponse response) {

if (Config.SHOW_LOG) {

Log.d(LOG_TAG, "onRequestFinished: " + requestId);

}

try {

if (requestId == mRequestId) {

mDataManager.removeOnDataListener(mRequestId, this);

mRequestId = -1;

final GetSessionUrl urlResponse = (GetSessionUrl) response.response;

mFilePath = urlResponse.mSessionUrl;

if (Config.SHOW_LOG) {

Log.d(LOG_TAG, "onRequestFinished, mFilePath: " + mFilePath);

}

if (mFilePath != null) {

playVideo();

} else {

showErrorMessage(mErrorGettingVideo);

}

}

} catch (Exception e) {

Log.e(LOG_TAG, "onRequestFinished", e);

}

}

@Override

public void onBufferingUpdate(MediaPlayer mPlayer, int percent) {

// TODO Auto-generated method stub

}

}

Les lignes en commentaires sont les lignes qui étaient là avant que j'utilise la librairie Vitamio.

Le lecteur se lance mais aucune vidéo n'apparaît.

Quelqu'un pourrait-il m'aider à re-modifier ce code source car j'y suis depuis plusieurs temps et je ne trouve vraiment rien.

2 fichiers de logs qui apparaissent de temps en temps sont en pièce jointe

Merci de votre aide !

Julian.

Lien vers le commentaire
Partager sur d’autres sites

Sujet à moitié résolu !

J'ai supprimé la librairie Vitamio, les imports de celle-ci, methodes et supprimé les commentaires afin de revenir à la librairie d'Android. J'ai mis en commentaire la ligne mMediaPlayer.setLooping(....); et ajouter mMediaPlayer.start() -> Le lecteur joue la vidéo mais sans le son et de plus à la fin de la vidéo, l'application plante et durant la lecture on ne peut pas arrêter la lecture pour revenir à la page précédente.

Quelqu'un a des idées ?

Modifié par broadpeak
Lien vers le commentaire
Partager sur d’autres sites

Rejoignez la conversation

Vous pouvez poster maintenant et vous enregistrez plus tard. Si vous avez un compte, connectez-vous maintenant pour poster.

Invité
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Répondre à ce sujet…

×   Collé en tant que texte enrichi.   Coller en tant que texte brut à la place

  Seulement 75 émoticônes maximum sont autorisées.

×   Votre lien a été automatiquement intégré.   Afficher plutôt comme un lien

×   Votre contenu précédent a été rétabli.   Vider l’éditeur

×   Vous ne pouvez pas directement coller des images. Envoyez-les depuis votre ordinateur ou insérez-les depuis une URL.

×
×
  • Créer...