Как создать потоковое видео для большого контента?
Я часами работал над созданием правильного проигрывателя потокового видео в Android и довольно успешно создал проигрыватель, который может очень хорошо воспроизводить небольшие материалы, такие как песни, трейлеры и т. Д. Но проигрыватель демонстрирует необычное поведение для большого контента, такого как фильмы и телепередачи, поскольку он требует много потоковой передачи, проигрыватель начинает отставать от таких данных. Может ли кто-нибудь помочь мне найти решение для такой проблемы.
Заранее спасибо...
Вот источник:
public class player extends Activity implements OnErrorListener,
OnPreparedListener {
/** Called when the activity is first created. */
private static final int UPDATE_FREQUENCY = 500;
private static final int STEP_VALUE = 4000;
private static final int DIALOG_KEY = 0;
private TextView currentTime, duration;
private VideoView videoView;
private SeekBar seekbar = null;
private View mediacontroller;
private ProgressDialog progressDialog = null;
private ImageButton playButton = null;
private ImageButton prevButton = null;
private ImageButton nextButton = null;
private boolean isMoveingSeekBar = false;
private boolean isMediaCtrlShown = false;
private final Handler handler = new Handler();
private boolean isStarted = true;
private String currentFile = "singham_320b";
private boolean isCustomSeekButtonClick = false;
private boolean isPauseButtonClick = false;
private static boolean isMyDialogShowing = false;
private static int percentageBuffer = 0;
private int mpCurrentPosition;
int hh = 00, mm = 00, ss = 00, ms = 00;
int i = 0;
int previouPosition = 0;
private Runnable onEverySecond=new Runnable() {
public void run() {
if (videoView!=null) {
seekbar.setProgress(videoView.getCurrentPosition());
}
if (!isPauseButtonClick) {
mediacontroller.postDelayed(onEverySecond, 1000);
}
}
};
private final Runnable updatePositionRunnable = new Runnable()
{
public void run()
{
updatePosition();
}
};
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setUpMyDialog();
showMyDialog();
videoView = (VideoView) findViewById(R.id.videoview);
getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
seekbar = (SeekBar) findViewById(R.id.seekbar);
currentTime = (TextView) findViewById(R.id.currentTime);
playButton = (ImageButton) findViewById(R.id.play);
prevButton = (ImageButton) findViewById(R.id.prev);
nextButton = (ImageButton) findViewById(R.id.next);
duration = (TextView) findViewById(R.id.duration);
mediacontroller = findViewById(R.id.mediacontroller);
videoView.setOnErrorListener(this);
videoView.setOnPreparedListener(this);
videoView.setOnTouchListener(new View.OnTouchListener()
{
@Override
public boolean onTouch(View v, MotionEvent event)
{
if (!isMediaCtrlShown)
{
mediacontroller.setVisibility(View.GONE);
isMediaCtrlShown = true;
}
else
{
mediacontroller.setVisibility(View.VISIBLE);
isMediaCtrlShown = false;
}
return false;
}
});
Uri video = Uri.parse("http://wpc.1B42.edgecastcdn.net/001B42/mobile/songs/pyaar_ka_punchnama/life_sahi_hai_320b.mp4");
videoView.setVideoURI(video);
seekbar.setOnSeekBarChangeListener(seekBarChanged);
playButton.setOnClickListener(onButtonClick);
nextButton.setOnClickListener(onButtonClick);
prevButton.setOnClickListener(onButtonClick);
}
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
// TODO Auto-generated method stub
return false;
}
public void calculateTime(int ms) {
ss = ms / 1000;
mm = ss / 60;
ss %= 60;
hh = mm / 60;
mm %= 60;
hh %= 24;
}
@Override
public void onPrepared(MediaPlayer mp)
{
dismissMyDialog();
videoView.start();
mediacontroller.setVisibility(View.VISIBLE);
isMediaCtrlShown = false;
seekbar.setProgress(0);
seekbar.setMax(videoView.getDuration());
ms = videoView.getDuration();
calculateTime(ms);
duration.setText("" + hh + ":" + mm + ":" + ss);
ms = videoView.getCurrentPosition();
calculateTime(ms);
currentTime.setText("" + hh + ":" + mm + ":" + ss);
playButton.setImageResource(android.R.drawable.ic_media_pause);
updatePosition();
isStarted = true;
mp.setOnBufferingUpdateListener(new OnBufferingUpdateListener()
{
// show updated information about the buffering progress
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent)
{
Log.d(this.getClass().getName(), "percent: " + percent);
percentageBuffer = percent;
secondarySeekBarProgressUpdater(percent);
// progress.setSecondaryProgress(percent);
if (i == 0)
{
i = i + 1;
previouPosition = mp.getCurrentPosition();
}
else if (i == 1)
{
if (mp.getCurrentPosition() == previouPosition)
{
if (!isPauseButtonClick)
{
showMyDialog();
if (percent == 100)
{
dismissMyDialog();
}
}
}
else
{
i = 0;
previouPosition = 0;
dismissMyDialog();
}
}
else if (isCustomSeekButtonClick)
{
isCustomSeekButtonClick = false;
if (mpCurrentPosition == mp.getCurrentPosition())
{
showMyDialog();
if (percent == 100)
{
dismissMyDialog();
}
}
else
{
dismissMyDialog();
}
}
}
});
mp.setOnSeekCompleteListener(new OnSeekCompleteListener()
{
public void onSeekComplete(MediaPlayer mp)
{
if (mp.isPlaying())
{
}
else
{
onStart();
onPause();
onStart();
}
}
});
}
private SeekBar.OnSeekBarChangeListener seekBarChanged = new SeekBar.OnSeekBarChangeListener()
{
@Override
public void onStopTrackingTouch(SeekBar seekBar)
{
isMoveingSeekBar = false;
}
@Override
public void onStartTrackingTouch(SeekBar seekBar)
{
isMoveingSeekBar = true;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser)
{
Log.e("",""+progress+""+percentageBuffer);
if (fromUser)
{
isCustomSeekButtonClick = fromUser;
videoView.seekTo(progress);
mpCurrentPosition = progress;
Log.e("OnSeekBarChangeListener", "onProgressChanged");
}
if (isMoveingSeekBar)
{
videoView.seekTo(progress);
Log.i("OnSeekBarChangeListener", "onProgressChanged");
}
}
};
private View.OnClickListener onButtonClick = new View.OnClickListener() {
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.play:
{
if (videoView.isPlaying())
{
handler.removeCallbacks(updatePositionRunnable);
isPauseButtonClick = true;
videoView.pause();
playButton.setImageResource(android.R.drawable.ic_media_play);
}
else
{
if (isStarted)
{
videoView.start();
isPauseButtonClick = false;
playButton.setImageResource(android.R.drawable.ic_media_pause);
updatePosition();
}
else
{
startPlay(currentFile);
isPauseButtonClick = false;
videoView.start();
}
}
break;
}
case R.id.next:
{
int seekto = videoView.getCurrentPosition() + STEP_VALUE;
if (seekto > videoView.getDuration())
seekto = videoView.getDuration();
videoView.pause();
videoView.seekTo(seekto);
/*
* try { Thread.sleep(15000); } catch (InterruptedException e) {
* // TODO Auto-generated catch block e.printStackTrace(); }
*/
// player.pause();
videoView.start();
break;
}
case R.id.prev: {
int seekto = videoView.getCurrentPosition() - STEP_VALUE;
if (seekto < 0)
seekto = 0;
videoView.pause();
videoView.seekTo(seekto);
// player.pause();
videoView.start();
break;
}
}
}
};
private void updatePosition()
{
handler.removeCallbacks(updatePositionRunnable);
seekbar.setProgress(videoView.getCurrentPosition());
ms = videoView.getCurrentPosition();
calculateTime(ms);
currentTime.setText("" + hh + ":" + mm + ":" + ss);
handler.postDelayed(updatePositionRunnable, UPDATE_FREQUENCY);
}
private void startPlay(String file)
{
Log.i("Selected: ", file);
// selelctedFile.setText(file);
seekbar.setProgress(0);
videoView.stopPlayback();
videoView.start();
seekbar.setMax(videoView.getDuration());
playButton.setImageResource(android.R.drawable.ic_media_pause);
updatePosition();
isStarted = true;
}
void setUpMyDialog()
{
if (progressDialog == null)
{
progressDialog = (ProgressDialog) onCreateDialog(DIALOG_KEY);
progressDialog = new ProgressDialog(player.this);
progressDialog.setMessage("Loading...");
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
}
}
void showMyDialog()
{
Log.e("showMyDialog***", "****" + isMyDialogShowing);
if (!isMyDialogShowing)
{
isMyDialogShowing = true;
Log.e("showMyDialog: true***", "****" + isMyDialogShowing);
if (progressDialog != null && !progressDialog.isShowing())
{
Log.e("showMyDialog: true***", "****progressDialog" + progressDialog.isShowing());
progressDialog.show();
}
else if(progressDialog == null)
{
setUpMyDialog();
progressDialog.show();
}
}
}
void dismissMyDialog()
{
Log.e("dismissMyDialog***", "****");
if (progressDialog != null && progressDialog.isShowing())
{
progressDialog.dismiss();
progressDialog = null;
isMyDialogShowing = false;
}
}
void killMyDialog()
{
isMyDialogShowing = false;
}
private void secondarySeekBarProgressUpdater(int percent){
seekbar.setSecondaryProgress(percent);
}
1 ответ
Моя интуиция говорит, что вы можете что-то упустить из виду, сосредоточившись на плеере, тем более что он отлично работает для небольшого контента. Задумывались ли вы о проверке потокового сервера? Если на сервере нет задачи потоковой передачи больших файлов, проигрыватель мало что может с этим поделать. Кроме того, вы можете настроить размер пакета с сервера, чтобы помочь проигрывателю управлять воспроизведением, используя меньшие куски (простите за каламбур) мультимедиа за раз. Попробуйте использовать бесплатный потоковый сервер Apple Darwin. Существует версия для Apache, Windows и других, и она очень настраиваема. Получить себе набор файлов разных размеров и попытаться установить, в каком размере воспроизведение начинает сбоить. That figure will give you a big clue as to where the problem lies, be it in the transmitted server packet size, the available memory in the Android environment, or elsewhere. Whatever the figure, try setting a smaller packet size from the server. This should give your player less work to do and hopefully improve playback.
You can obtain the Darwin server from many places online. Here is one such link. Wikipedia has some useful information and some links for this server too, find them here. Good luck with your research on this.
Фрэнк.