Android在MediaPlayer中显示视频流并使用MediaCodec进行编码

时间:2015-07-15 14:03:40

标签: android video android-mediaplayer mediacodec

问题: 我有来自GoPro相机的视频流,格式为.m3u8。我需要在应用程序中显示流的内容,然后流式传输视频。 对于流媒体,我有与MediaCodec和ffmpeg一起使用的库。我应该能够流式传输MediaCodec的outputBuffer。

我可以在SurfaceView上使用MediaPlayer流式传输视频,没问题。 真正的困难在于使用MediaCodec。 我可以初始化MediaCodec,获取表面并将其添加到MediaPlayer - 蒸汽播放 - 我可以听到声音。

现在问题:

  1. 在SurfaceView上显示流 - 或MP和MC可以使用的任何其他视图。 从Surface到SurfaceView / TextureView显示数据的最佳方法是什么?

  2. 我无法从MediaCodec获取数据。 我只需要支持5.0+设备,所以我尝试使用MediaCodec.Callback。但我每次都会得到错误。我还没有找到错误的含义。 我可以做些什么来配合回拨工作?

  3. 有没有“简单”的方法,或者我必须像Google Grafika一样深入缓冲区和表面?

  4. 以下是我得到的错误:

    E/ACodec﹕ [OMX.qcom.video.encoder.avc] storeMetaDataInBuffers (output) failed w/ err -2147483648
    
     1877-1904/com.example.marek.goprorecorder E/ACodec﹕ [OMX.qcom.video.encoder.avc] ERROR(0x80001009)
    07-15 15:54:47.411    1877-1904/com.example.marek.goprorecorder E/ACodec﹕ signalError(omxError 0x80001009, internalError -2147483648)
    07-15 15:54:47.411    1877-1903/com.example.marek.goprorecorder E/MediaCodec﹕ Codec reported err 0x80001009, actionCode 0, while in state 6
    
    Errror mess: android.media.MediaCodec$CodecException: Error 0x80001009
    07-15 15:54:47.454    1877-1877/com.example.marek.goprorecorder D/MediaCodecCallback﹕ Errror diag: android.media.MediaCodec.error_neg_2147479543
    07-15 15:54:47.454    1877-1877/com.example.marek.goprorecorder D/MediaCodecCallback﹕ Errror rec: false
    07-15 15:54:47.454    1877-1877/com.example.marek.goprorecorder D/MediaCodecCallback﹕ Errror tra: false
    

    这是我的活动:

    public class MainActivity extends ActionBarActivity implements MediaPlayer.OnPreparedListener{
        private final MediaPlayer mp = new MediaPlayer();
        private Surface encoderSurface;
        private static final String MIME_TYPE = "video/avc";    // H.264 Advanced Video Coding
        private static final int FRAME_RATE = 30;               // 30fps
        private static final int IFRAME_INTERVAL = 0;           // 5 seconds between I-frames
        private static final File OUTPUT_DIR = Environment.getExternalStorageDirectory();
        MediaCodec encoder = null;
        MediaCodec.BufferInfo mBufferInfo;
        TextureView surfaceView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            int width = 432;
            int height = 240;
            prepareEncoder(width, height, 600000);
        }
    
        private void prepareEncoder(int width, int height, int bitRate) {
            mBufferInfo = new MediaCodec.BufferInfo();
            MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
            format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
            format.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
            format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
            format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
    
            try {
                encoder = MediaCodec.createEncoderByType(MIME_TYPE);
            } catch (IOException e) {
                e.printStackTrace();
            }
            CodecCallback callback = new CodecCallback();
            encoder.setCallback(callback);
            encoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            encoderSurface = encoder.createInputSurface();
            preparePlayer(encoderSurface);
            encoder.start();
        }
    
        void preparePlayer(Surface s) {
            try {
                //mp.setDataSource("http://10.5.5.9:8080/live/amba.m3u8");
                mp.setDataSource("http://playertest.longtailvideo.com/adaptive/oceans_aes/oceans_aes.m3u8");
                mp.setSurface(s);
                mp.prepare();
                mp.setOnPreparedListener(this);
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (IllegalStateException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        @Override
        public void onPrepared(MediaPlayer mp) {
            mp.start();
        }
    
        private class CodecCallback extends Callback {
    
            @Override
            public void onInputBufferAvailable(MediaCodec codec, int index) {
                Log.d("MediaCodecCallback","InputBufferAvailable "+index);
            }
    
            @Override
            public void onOutputBufferAvailable(MediaCodec codec, int index, MediaCodec.BufferInfo info) {
                ByteBuffer outBuffer = codec.getOutputBuffer(index);
                Log.d("MediaCodecCallback", "OutputBuffer Position: " + outBuffer.position());
                Log.d("MediaCodecCallback", "OutputBuffer Limit: " + outBuffer.limit());
                Log.d("MediaCodecCallback", "OutputBuffer Capacity: " + outBuffer.capacity());
                Log.d("MediaCodecCallback","OutputBuffer: "+outBuffer.toString());
                encoder.releaseOutputBuffer(index, false);
            }
    
            @Override
            public void onError(MediaCodec codec, MediaCodec.CodecException e) {
                Log.d("MediaCodecCallback","Errror mess: " + e);
                Log.d("MediaCodecCallback","Errror diag: " + e.getDiagnosticInfo());
                Log.d("MediaCodecCallback","Errror rec: " + e.isRecoverable());
                Log.d("MediaCodecCallback","Errror tra: " + e.isTransient());
            }
    
            @Override
            public void onOutputFormatChanged(MediaCodec codec, MediaFormat format) {
                Log.d("MediaCodecCallback","OutputFormatChanged: " + format.toString());
            }
        }
    
    
    }
    

    编辑1:

    这是将输出添加到SurfaceTexture的正确方法吗?

    @Override
        public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
            Surface s = new Surface(surface);
            preparePlayer(s); //ads Surface to MediaPlayer and starts to play the stream
        }
    

    我可以使用fromSurfaceTextureUpdate获得的surfaceTexture吗?

    @Override
        public void onSurfaceTextureUpdated(SurfaceTexture surface) {           
    
        }
    
    • 另一个问题,您是否有示例如何将SurfaceTexture渲染到Surface? 谢谢!

0 个答案:

没有答案