우선 코드 동작방식은 다음과 같습니다.
1. 액티비티에 CustomMainVideoView라는 커스텀 뷰를 생성합니다. 이 커스텀뷰는 영상의 크기에따라 가변적으로 사이즈가 변경되는 커스텀 뷰 입니다.
2. CustomMainVideoView는 ExoPlayer 라이브러이의 PlayerView와 ImageView를 리스트에 삽입된 데이터에 맞게 표출하는 역할을 하며, 전반적인 작동은 MyExoPlayer라는 싱글톤 패턴의 객체에서 수행합니다.
3. 따라서, CustomMainVideoView는 최초 레이아웃에 뷰를 삽입하는 경우, 리스트를 불러오는 경우에 작동하며, 이후의 작동은 MyExoPlayer라는 객체에서 컨트롤합니다.
4. MyExoPlayer는 CustomMainVideoView에서 가져온 리스트를 기반으로 영상 재생, 이미지 재생 등을 명령하는 클래스입니다.
5. 이 클래스에서 PlayerView의 초기화를 1회 수행 후, 리스트의 현재 인덱스가 비디오면 Exoplayer로, 이미지면 ImageView로 재생되도록 실행합니다.
6. 실행이 끝나면 인덱스를 1 증가시키고, 마지막 인덱스인 경우에는 인덱스를 0으로 변경하며, 재귀함수로써 반복합니다.
문제는 이 프로그램을 대략 30~40시간정도 재생시키면 영상이 까맣게 변경되며, 오디오출력만 있을 뿐, 비디오 출력은 일어나지 않습니다.
아래 코드는 핵심이 되는 5번 항목에 대한 소스코드로, 보시다시피 재귀함수로 되어있습니다.
오류는 아주 불규칙적으로 일어나며, 오래는 1주일 이상정도, 짧게는 이틀정도 안에 오류가 발견되었습니다.
어디가 문제일까요?
this.localVideoMode = localVideoMode;
isReleasedView = false;
Log.d(TAG, "initializePlayer: init");
if (index >= sample.length) {
index = 0;
}
if (sample[index].contains(".mp4")) {
setCurrentViewVisibility(VIDEO_VIEW);
Log.d(TAG, "initializePlayer: index: " + index + "sample.length: " + sample.length);
this.isImageShow = false;
if (player == null) {
player = ExoPlayerFactory.newSimpleInstance(context, trackSelector);
playerView.setPlayer(player);
}
playerView.hideController();
MediaSource mediaSource;
mediaSource = getMediaSource(sample[index], localVideoMode, serverAddress);
final int finalIndex = index + 1;
if (mediaSource == null) {
releasePlayer();
initializePlayer(sample, finalIndex, localVideoMode, serverAddress);
} else {
final Player.EventListener eventListener = new Player.EventListener() {
@Override
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_ENDED) {
try {
player.removeListener(this);
} catch (NullPointerException e) {
e.printStackTrace();
}
releasePlayer();
initializePlayer(sample, finalIndex, localVideoMode, serverAddress);
}
}
@Override
public void onPlayerError(ExoPlaybackException error) {
player.removeListener(this);
releasePlayer();
initializePlayer(sample, finalIndex, localVideoMode, serverAddress);
error.printStackTrace();
}
};
player.prepare(mediaSource, true, false);
player.addListener(eventListener);
player.setPlayWhenReady(true);
player.addVideoListener(new VideoListener() {
@Override
public void onVideoSizeChanged(int width, int height, int unappliedRotationDegrees, float pixelWidthHeightRatio) {
if (width >= height) {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) playerViewLayout.getLayoutParams();
params.height = (int) ((float) height * (params.width-25) / (float) width) + 25;
playerViewLayout.setLayoutParams(params);
} else {
RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) playerViewLayout.getLayoutParams();
params.width = 450;
params.height = (int) ((float) height * (params.width-25) / (float) width) + 25;
playerViewLayout.setLayoutParams(params);
}
}
@Override
public void onRenderedFirstFrame() {
}
});
}
} else {
try {
this.isImageShow = true;
File file = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/KIOSKData/video/", sample[index]);
showGlideImage(file);
imageViewLayout.setVisibility(VISIBLE);
playerViewLayout.setVisibility(INVISIBLE);
final int finalIndex = index + 1;
imageHandler = new Handler();
imageRunnable = new Runnable() {
@Override
public void run() {
initializePlayer(sample, finalIndex, localVideoMode, serverAddress);
}
};
imageHandler.postDelayed(imageRunnable, 10000);
} catch (IllegalArgumentException e) {
releaseView();
}
}