마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드 ExoPlayer2 에러 질문드립니다.

0 추천

현재 ViewPager2 + recyclerview Adapter를 이용해서 페이징이 가능한 비디오플레이어를 만들고 있습니다.

서버에서 hls(.m3u8) uri를 불러와 플레이를 시키는데 처음엔 잘 됩니다.

다만 플레이가 20~30회 정도가 되면 그때부터 에러가 뜨고 블랙스크린이 뜨면서 플레이가 안되더라구요

에러를 봐도 어떻게 접근해야 하는지 몰라 글을 올립니다.

아 HLS는 서버에서 MP4 파일을 ffmpeg을 통해 .m3u8파일로 변환하고 있습니다.

MP4파일을 그대로 실행시켜도 같은 에러가 뜹니다..;;

ffmpeg코드 입니다.

ffmpeg -i ./vod/$vod.mp4 -vcodec libx264 -profile:v baseline -level 3.0 -s 640x640 -start_number 0 -hls_time 10 -hls_list_size 0 -f hls ./vod/$vod.m3u8

어댑터부분 코드입니다.

public class PageAdapter extends RecyclerView.Adapter<PageAdapter.PGHolder>{
        private ArrayList<ViewPager_Item> viewPagerItems;
        public PageAdapter(ArrayList itemlist) ...

        @NonNull
        @Override
        public PGHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) ....


        @Override
        public void onBindViewHolder(@NonNull PGHolder holder, int position) {

            if(holder.player == null){

                holder.player = ExoPlayerFactory.newSimpleInstance(getActivity());

                holder.exoplayerview.setPlayer(holder.player);
            }

            if(viewPagerItems.size() > 0) {
                Uri uri = Uri.parse(viewPagerItems.get(position).vod);
                String userAgent = Util.getUserAgent(getActivity(), "MyApplication");
                MediaSource mediaSource = new HlsMediaSource.Factory(new DefaultHttpDataSourceFactory(userAgent)).createMediaSource(uri);
                LoopingMediaSource loopingMediaSource = new LoopingMediaSource(mediaSource);

                holder.player.prepare(loopingMediaSource);

                holder.player.seekTo(100);
            }
        }

        @Override
        public int getItemCount() {
            return viewPagerItems.size();
        }

        @Override
        public void onViewAttachedToWindow(@NonNull PGHolder holder) {
            super.onViewAttachedToWindow(holder);


            viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
                @Override
                public void onPageSelected(int position) {
                    super.onPageSelected(position);

                    if(holder.getAdapterPosition() == position){

                        holder.player.setPlayWhenReady(true);

                        holder.layout.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                //holder.player.setPlayWhenReady(!holder.player.getPlayWhenReady());

                                if(holder.player.getPlayWhenReady()){ //play

                                    holder.player.setPlayWhenReady(false);
                                    holder.playimg.setVisibility(View.VISIBLE);

                                }else{ //puase

                                    holder.player.setPlayWhenReady(true);
                                    holder.playimg.setVisibility(View.GONE);
                                }

                            }
                        }); //setonclicklistener
                    }
                }

            });

        }

        @Override
        public void onViewDetachedFromWindow(@NonNull PGHolder holder) {
            super.onViewDetachedFromWindow(holder);

            holder.player.setPlayWhenReady(false);
            holder.player.seekTo(100);

        }


        public class PGHolder extends RecyclerView.ViewHolder{

            public HashTagHelper mTextHashTagHelper;
            public ConstraintLayout layout;

            public PlayerView exoplayerview;
            public SimpleExoPlayer player;


            public PGHolder(final View itemView) {
                super(itemView);

                layout = (ConstraintLayout) itemView.findViewById(R.id.layout);

                exoplayerview = itemView.findViewById(R.id.exoplayerview);

            }//PGHolder
        }
    }
로아 (320 포인트) 님이 5월 21일 질문
Logcat에 뜬 에러코드입니다


2020-05-21 12:37:15.775 25900-26633/com.playhead.plop E/C2AllocatorIon: >>>SEC mapUsage Init ffffffff
2020-05-21 12:37:15.812 25900-26638/com.playhead.plop E/ACodec: Unable to instantiate codec 'OMX.Exynos.avc.dec' with err 0xfffffff4.
2020-05-21 12:37:15.813 25900-26638/com.playhead.plop E/ACodec: signalError(omxError 0xfffffff4, internalError -12)
2020-05-21 12:37:15.813 25900-26637/com.playhead.plop E/MediaCodec: Codec reported err 0xfffffff4, actionCode 0, while in state 1
2020-05-21 12:37:15.816 25900-26619/com.playhead.plop E/ExoPlayerImplInternal: Playback error.
    com.google.android.exoplayer2.ExoPlaybackException: com.google.android.exoplayer2.mediacodec.MediaCodecRenderer$DecoderInitializationException: Decoder init failed: OMX.Exynos.avc.dec, Format(0, null, null, video/avc, avc1.42C01E, -1, null, [640, 640, -1.0], [-1, -1])
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodec(MediaCodecRenderer.java:516)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1190)
        at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:636)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.readToFlagsOnlyBuffer(MediaCodecRenderer.java:737)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:648)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:575)
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:326)
        at android.os.Handler.dispatchMessage(Handler.java:103)
        at android.os.Looper.loop(Looper.java:237)
        at android.os.HandlerThread.run(HandlerThread.java:67)
     Caused by: com.google.android.exoplayer2.mediacodec.MediaCodecRenderer$DecoderInitializationException: Decoder init failed: OMX.Exynos.avc.dec, Format(0, null, null, video/avc, avc1.42C01E, -1, null, [640, 640, -1.0], [-1, -1])
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:790)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodec(MediaCodecRenderer.java:514)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1190) 
        at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:636) 
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.readToFlagsOnlyBuffer(MediaCodecRenderer.java:737) 
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:648) 
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:575) 
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:326) 
        at android.os.Handler.dispatchMessage(Handler.java:103) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.os.HandlerThread.run(HandlerThread.java:67) 
     Caused by: android.media.MediaCodec$CodecException: Failed to initialize OMX.Exynos.avc.dec, error 0xfffffff4
        at android.media.MediaCodec.native_setup(Native Method)
        at android.media.MediaCodec.<init>(MediaCodec.java:1864)
        at android.media.MediaCodec.createByCodecName(MediaCodec.java:1842)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.initCodec(MediaCodecRenderer.java:848)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodecWithFallback(MediaCodecRenderer.java:783)
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.maybeInitCodec(MediaCodecRenderer.java:514) 
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.onInputFormatChanged(MediaCodecRenderer.java:1190) 
        at com.google.android.exoplayer2.video.MediaCodecVideoRenderer.onInputFormatChanged(MediaCodecVideoRenderer.java:636) 
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.readToFlagsOnlyBuffer(MediaCodecRenderer.java:737) 
        at com.google.android.exoplayer2.mediacodec.MediaCodecRenderer.render(MediaCodecRenderer.java:648) 
        at com.google.android.exoplayer2.ExoPlayerImplInternal.doSomeWork(ExoPlayerImplInternal.java:575) 
        at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:326) 
        at android.os.Handler.dispatchMessage(Handler.java:103) 
        at android.os.Looper.loop(Looper.java:237) 
        at android.os.HandlerThread.run(HandlerThread.java:67) 


추가로

2020-05-21 12:26:54.111 23835-24037/com.example.plop E/C2AllocatorIon: >>>SEC mapUsage Init ffffffff
2020-05-21 12:26:54.551 23835-24054/com.example.plop E/C2AllocatorIon: >>>SEC mapUsage Init ffffffff

이런것도 뜨던데 이게 뭘까요??

2개의 답변

0 추천
로그에 아래와 같은 내용이 있는것으로 보아선 HW 코덱을 생성하다 실패해서 오류가 난듯 합니다.

E/ACodec: signalError(omxError 0xfffffff4, internalError -12)
DecoderInitializationException: Decoder init failed

 

반복하여  exoplayer 객체 생성하면서, 기존 exoplayer 객체를  제대로 release (holder.player.release() 호출)  하지 않아

 HW 코덱 핸들을 기존 플레이어에서 가지고 있어서, 더이상 할당하지 못 하고 오류가 난 것으로 생각되니 확인 해 보세요.
익명사용자 님이 5월 21일 답변
5월 21일 수정
역시나 release를 안한탓인가요...
근데 질문이 있습니다.. Viewpager2라서 recyclerviewAdapter를 사용하고 있는데요

release를 사용해야한다고 하면 onViewAttachedToWindow이곳에서 uri를 가져와 player에 넣고 onViewDetachedFromWindow에서 release하면 되겠지만

현재 페이지의 -1,+1 페이지는 미리 로딩해놓고 싶습니다.. 이부분은 어떻게 처리할 수 있을까요??
0 추천
익명으로는 댓글이 안되서 답변하기로 적습니다.   

http://dktfrmaster.blogspot.com/2018/11/paging-library.html 를 참조해서, PagedListAdapter 에 해당 사항을 구현 하시면 되실 듯 합니다.
익명사용자 님이 5월 21일 답변
...