MediaExtractorで再生を停止する方法

2,054 views
Skip to first unread message

root0hac...@nifty.com

unread,
Oct 20, 2013, 11:31:06 AM10/20/13
to android-...@googlegroups.com
githubのサンプルコードですが、MediaExtractorで再生~停止、シークは出来るのですが、ポーズ~再生が出来なくて困ってます。sdkにはそのようなコマンドもないみたいですし、どなたか分かるかたいませんでしょうか?
どうもextractorの内部時間が停止出来ないと、再生停止から再生を開始するとextractorの内部時間の位置まで早回し再生してしまうみたいで、困ってます。

以下サンプルです。

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.res.Configuration;
import android.media.AudioTrack;
import android.media.MediaCodec;
import android.media.MediaCodec.BufferInfo;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Bundle;
import android.os.Handler;
import android.util.Log;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.LinearLayout;
import android.widget.MediaController;



public class DecodePlayer extends Activity implements SurfaceHolder.Callback, MediaController.MediaPlayerControl {
    private static String SAMPLE;
    int select_position=0;
    File outputFilename;
    String outputFileStringName;
     MediaFormat format;
    String SrcPath;
    private static final String TAG = "DecodeActivity";
    private PlayerThread mPlayer = null;
    private MediaController mediaController;
    private long lastPresentationTimeUs;
    private boolean seeked = false;
    private long startMs;
   
   
    private long startTime;
   
   
   
    private long diff = 0;
    private long lastSeekedTo = 0;
    private long lastCorrectPresentationTimeUs = 0;
    //ビューを重ねて表示するためのレイアウト
    private FrameLayout mFrameLayout;
    public static SurfaceHolder holder;

    int play_start=1;
    long offset=0;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

           //フルスクリーン表示にします
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
        //タイトルバーを非表示にします
        requestWindowFeature(Window.FEATURE_NO_TITLE);

        Context context_app = this.getApplicationContext();


        //  スリープを無効に
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        Configuration config = getResources().getConfiguration();



        SurfaceView sv = new SurfaceView(this);
        mediaController = new MediaController(this);

        LinearLayout linearLayout = new LinearLayout(this);
        linearLayout.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.FILL_PARENT, ViewGroup.LayoutParams.FILL_PARENT));
        linearLayout.addView(sv);





        sv.getHolder().addCallback(this);
        setContentView(linearLayout);

     



           //ビデオソースパスをここで受け取る
           Intent intent = getIntent();
           SrcPath = intent.getStringExtra("SrcPath");
           select_position=intent.getIntExtra("position", 0);


           outputFilename=new File(SrcPath);
           outputFileStringName=outputFilename.getName();
           SAMPLE = SrcPath;






        mediaController.setAnchorView(sv);
        mediaController.setMediaPlayer(this);






    }

    protected void onDestroy() {
        super.onDestroy();
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        if (mPlayer == null) {
            final Handler h = new Handler();
            h.post(new Runnable() {
                @Override
                public void run() {
                    try {
                        mediaController.show();
                        h.postDelayed(this, 2000);
                    } catch (Exception e) {

                    }
                }
            });


            mPlayer = new PlayerThread(this, holder.getSurface());
            mPlayer.start();
        }
    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        if (mPlayer != null) {
            mPlayer.interrupt();
        }
    }

    @Override
    public void start() {
        mPlayer.play();
    }

    @Override
    public void pause() {
        mPlayer.pause();
       
      //  mPlayer.stop();
       
       
       
    }

    @Override
    public int getDuration() {
        return (int) mPlayer.duration;
    }

    @Override
    public int getCurrentPosition() {
        return mPlayer.getCurrentPosition();
    }

    @Override
    public void seekTo(int i) {
        mPlayer.seekTo(i);
        mediaController.show();
    }

    @Override
    public boolean isPlaying() {
        if (mPlayer != null)
            return mPlayer.isPlaying();
        else
            return false;
    }

    @Override
    public int getBufferPercentage() {
        return 0; //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public boolean canPause() {
        return true; //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public boolean canSeekBackward() {
        return false; //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public boolean canSeekForward() {
        return false; //To change body of implemented methods use File | Settings | File Templates.
    }

    private class PlayerThread extends Thread {
        Handler handler = new Handler();
        MediaController.MediaPlayerControl mediaPlayerControl;
        Handler handler1 = new Handler();
        long lastOffset = 0;
        boolean isPlaying = false;
        private MediaExtractor extractor;
        private MediaCodec decoder;
        private Surface surface;
        private BufferInfo info;
        private long duration;
        private AudioTrack audioTrack;

        public PlayerThread(MediaController.MediaPlayerControl mediaPlayerControl, Surface surface) {
            this.surface = surface;
            this.mediaPlayerControl = mediaPlayerControl;
        }

        @Override
        public void run() {
            MediaCodecPlay();
        }

        private void MediaCodecPlay() {
            extractor = new MediaExtractor();
           // extractor.setDataSource(SAMPLE);
           
           
            File f = new File(SAMPLE);
            FileInputStream fileIS = null;
            FileDescriptor fd = null;
           
           
            try {
               
               
                fileIS = new FileInputStream(f);
                fd = fileIS.getFD();
            } catch (IOException e1) {
                // TODO 自動生成された catch ブロック
                e1.printStackTrace();
            }
           
            //extractor.setDataSource(fd, lastOffset, f.length());
           
            extractor.setDataSource(fd, 0, f.length());
           
           
           
           
           

            format = null;
            for (int i = 0; i < extractor.getTrackCount(); i++) {
                format = extractor.getTrackFormat(i);
                String mime = format.getString(MediaFormat.KEY_MIME);
                duration = format.getLong(MediaFormat.KEY_DURATION) / 1000;

    

                if (mime.startsWith("video/")) {
                    extractor.selectTrack(i);
                    decoder = MediaCodec.createDecoderByType(mime);
                    decoder.configure(format, surface, null, 0);
                    break;
                }
            }

            decoder.start();
           

            ByteBuffer[] inputBuffers = decoder.getInputBuffers();
            ByteBuffer[] outputBuffers = decoder.getOutputBuffers();
            info = new BufferInfo();
            startMs = System.currentTimeMillis();
            startTime=System.nanoTime()/1000;
           
        

            boolean isEOS = false;
      while (!Thread.interrupted())
      {
         
      
                if (!isEOS)
                {
                    int inIndex = decoder.dequeueInputBuffer(1000);
                    if (inIndex >= 0) {
                        ByteBuffer buffer = inputBuffers[inIndex];

                        int sampleSize;
                       
                       
                   
                       
                        sampleSize = extractor.readSampleData(buffer, 0);
                       
                       
                       
                        offset=offset+sampleSize;
                       
                       
                        if (sampleSize < 0) {
                     
                            decoder.queueInputBuffer(inIndex, 0, 0, 0, MediaCodec.BUFFER_FLAG_END_OF_STREAM);
                            isEOS = true;
                        }
                        else
                        {
        
                           
                             if(play_start==1)
                             {
                                 
                                 
                
                                  decoder.queueInputBuffer(inIndex, 0, sampleSize, extractor.getSampleTime(), 0);
                                 
                                  //extractor.advance()で次のフレームをデコードするが、再生を停止させても内部の時間が進んでいくため、再生を開始すると早回しシークしてしまう??

                                  extractor.advance();
                             }
                             else
                             {
     
                //ここでポーズさせているが、再生開始時に最初から早回しシーク動作が入り20秒程度再生開始まで必要??
                                    decoder.queueInputBuffer(inIndex, 0, 0,(int)( extractor.getSampleTime()), 0);
                                    extractor.advance();
                                 while(play_start==0)
                                 {
                                     
                                     
                                 }
               
                                 
                             }
                           
          
                           
                           
                        }
      
                       
                    }
                }

                int outIndex = decoder.dequeueOutputBuffer(info, 1000);

                if (info.presentationTimeUs < lastPresentationTimeUs) { // correct timing playback issue for some videos
                    startMs = System.currentTimeMillis();
                    lastCorrectPresentationTimeUs = lastPresentationTimeUs;
                }


                switch (outIndex)
                {
                    case MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED:
                 
                        outputBuffers = decoder.getOutputBuffers();
                        break;
                    case MediaCodec.INFO_OUTPUT_FORMAT_CHANGED:
                  
                        break;
                    case MediaCodec.INFO_TRY_AGAIN_LATER:
                
                        break;
                    default:
                        ByteBuffer buffer = outputBuffers[outIndex];
                        lastPresentationTimeUs = info.presentationTimeUs;

                        if (seeked && Math.abs(info.presentationTimeUs / 1000 - lastOffset) < 100)
                            seeked = false;

                        while (!seeked && (info.presentationTimeUs / 1000 - lastOffset) > System.currentTimeMillis() - startMs)
                        {
                            try {
                                sleep(5);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                                break;
                            }
                        }
               
                       
                       

                        decoder.releaseOutputBuffer(outIndex, true);
                        break;
                }

   
                if ((info.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
                 
                    break;
                }
           
 
               
      }

            decoder.stop();
            decoder.release();
            extractor.release();

        }

        public int getCurrentPosition() {
            if (info != null)
                return (int) (info.presentationTimeUs / 1000);
            else
                return 0;
        }

        public void seekTo(int i) {
            seeked = true;
 
            extractor.seekTo(i * 1000, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
    

            lastOffset = extractor.getSampleTime() / 1000;
            startMs = System.currentTimeMillis();
            diff = (lastOffset - lastPresentationTimeUs / 1000);

     
        }

        public void pause() {
           
           
      
            play_start=0;
            isPlaying = false;
        }

        public void play() {
       
       
           
            play_start=1;
           
            isPlaying = true;
             
        }

        public boolean isPlaying() {
            return isPlaying;
        }
    }

}

Reply all
Reply to author
Forward
0 new messages