Android播放器實現視頻窗口實時放大縮小功能


很多開發者希望Android播放端實現視頻窗口的放大縮小功能,為此,我們做了個簡單的demo,通過播放端回調RGB數據,直接在上層view操作處理即可,Github:https://github.com/daniulive/SmarterStreaming

無視頻無真相:http://www.iqiyi.com/w_19s9sa7epp.html

基本流程如下:

1. 基礎的初始化和參數設定

        libPlayer = new SmartPlayerJniV2(); myContext = this.getApplicationContext(); sSurfaceView = (SurfaceView) this.findViewById(R.id.surface); surface_renderer = new RGBSurfaceRenderer(sSurfaceView);
private void InitAndSetConfig() { playerHandle = libPlayer.SmartPlayerOpen(myContext); if (playerHandle == 0) { Log.e(TAG, "surfaceHandle with nil.."); return; } libPlayer.SetSmartPlayerEventCallbackV2(playerHandle, new EventHandeV2()); libPlayer.SmartPlayerSetBuffer(playerHandle, playBuffer); // set report download speed(默認2秒一次回調 用戶可自行調整report間隔) libPlayer.SmartPlayerSetReportDownloadSpeed(playerHandle, 1, 2); libPlayer.SmartPlayerSetFastStartup(playerHandle, isFastStartup ? 1 : 0); //設置RTSP超時時間 int rtsp_timeout = 10; libPlayer.SmartPlayerSetRTSPTimeout(playerHandle, rtsp_timeout); //設置RTSP TCP/UDP模式自動切換 int is_auto_switch_tcp_udp = 1; libPlayer.SmartPlayerSetRTSPAutoSwitchTcpUdp(playerHandle, is_auto_switch_tcp_udp); libPlayer.SmartPlayerSaveImageFlag(playerHandle, 1); // It only used when playback RTSP stream.. // libPlayer.SmartPlayerSetRTSPTcpMode(playerHandle, 1); playbackUrl = "rtmp://202.69.69.180:443/webcast/bshdlive-pc"; //playbackUrl = "rtsp://184.72.239.149/vod/mp4://BigBuckBunny_175k.mov"; libPlayer.SmartPlayerSetUrl(playerHandle, playbackUrl); }

2.  設置External Render,回調RGBA數據

libPlayer.SmartPlayerSetExternalRender(playerHandle, new RGBAExternalRender());

Log.i(TAG, "Start playback stream++"); InitAndSetConfig(); // External Render libPlayer.SmartPlayerSetExternalRender(playerHandle, new RGBAExternalRender()); libPlayer.SmartPlayerSetAudioOutputType(playerHandle, 0); if (isMute) { libPlayer.SmartPlayerSetMute(playerHandle, isMute ? 1 : 0); } if (isHardwareDecoder) { int isSupportHevcHwDecoder = libPlayer.SetSmartPlayerVideoHevcHWDecoder(playerHandle, 1); int isSupportH264HwDecoder = libPlayer .SetSmartPlayerVideoHWDecoder(playerHandle, 1); Log.i(TAG, "isSupportH264HwDecoder: " + isSupportH264HwDecoder + ", isSupportHevcHwDecoder: " + isSupportHevcHwDecoder); } libPlayer.SmartPlayerSetLowLatencyMode(playerHandle, isLowLatency ? 1 : 0); libPlayer.SmartPlayerSetFlipVertical(playerHandle, is_flip_vertical ? 1 : 0); libPlayer.SmartPlayerSetFlipHorizontal(playerHandle, is_flip_horizontal ? 1 : 0); libPlayer.SmartPlayerSetRotation(playerHandle, rotate_degrees); int iPlaybackRet = libPlayer .SmartPlayerStartPlay(playerHandle); if (iPlaybackRet != 0) { Log.e(TAG, "Call SmartPlayerStartPlay failed.."); return; } surface_renderer.StartRender(); btnStartStopPlayback.setText("停止播放 "); isPlaying = true; Log.i(TAG, "Start playback stream--");

3. 回調RGBA數據:

   class RGBAExternalRender implements NTExternalRender { // public static final int NT_FRAME_FORMAT_RGBA = 1; // public static final int NT_FRAME_FORMAT_ABGR = 2; // public static final int NT_FRAME_FORMAT_I420 = 3; private int width_ = 0; private int height_ = 0; private int row_bytes_ = 0; private ByteBuffer rgba_buffer_ = null; @Override public int getNTFrameFormat() { Log.i(TAG, "RGBAExternalRender::getNTFrameFormat return " + NT_FRAME_FORMAT_RGBA); return NT_FRAME_FORMAT_RGBA; } @Override public void onNTFrameSizeChanged(int width, int height) { width_ = width; height_ = height; row_bytes_ = width_ * 4; Log.i(TAG, "RGBAExternalRender::onNTFrameSizeChanged width_:" + width_ + " height_:" + height_); rgba_buffer_ = ByteBuffer.allocateDirect(row_bytes_ * height_); } @Override public ByteBuffer getNTPlaneByteBuffer(int index) { if (index == 0) { return rgba_buffer_; } else { Log.e(TAG, "RGBAExternalRender::getNTPlaneByteBuffer index error:" + index); return null; } } @Override public int getNTPlanePerRowBytes(int index) { if (index == 0) { return row_bytes_; } else { Log.e(TAG, "RGBAExternalRender::getNTPlanePerRowBytes index error:" + index); return 0; } } public void onNTRenderFrame(int width, int height, long timestamp) { if (rgba_buffer_ == null) return; // rgba_buffer_.rewind(); // copy buffer // test // byte[] test_buffer = new byte[16]; // rgba_buffer_.get(test_buffer); //Log.i(TAG, "RGBAExternalRender:onNTRenderFrame w=" + width + " h=" // + height + " timestamp=" + timestamp); // Log.i(TAG, "RGBAExternalRender:onNTRenderFrame rgba:" + // bytesToHexString(test_buffer)); if ( surface_renderer != null) { surface_renderer.SetRGBImage(width, height, rgba_buffer_); } } }

4. 對視頻view進行放大縮小等狀態處理:

        @SuppressLint("ClickableViewAccessibility") public RGBSurfaceRenderer(SurfaceView view) { surface_holder_ = view.getHolder(); if (surface_holder_ == null) { Log.e(TAG, "RGBSurfaceRenderer, surfaceHolder with null.."); return; } surface_holder_.addCallback(this); view.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { Log.e(TAG, "onTouch called.."); switch (event.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: start_point_.set(event.getX(), event.getY()); status_ = DRAG; break; case MotionEvent.ACTION_POINTER_DOWN: float distance = spacing(event); if (distance > 10f) { status_ = ZOOM; start_distance_ = distance; } break; case MotionEvent.ACTION_MOVE: if (status_ == DRAG) { dragAction(event); } else { if (event.getPointerCount() == 1) return true; zoomAcition(event); } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_POINTER_UP: status_ = NONE; break; default: break; } return true; } }); } 

5. 關閉播放:

if (isPlaying) { Log.i(TAG, "Stop playback stream++"); int iRet = libPlayer.SmartPlayerStopPlay(playerHandle); if (iRet != 0) { Log.e(TAG, "Call SmartPlayerStopPlay failed.."); return; } surface_renderer.StopRender(); libPlayer.SmartPlayerClose(playerHandle); playerHandle = 0; isPlaying = false; btnStartStopPlayback.setText("開始播放 "); Log.i(TAG, "Stop playback stream--"); } 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM