package com.xypower.mplive; import android.Manifest; import android.content.Intent; import android.content.SharedPreferences; import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.hardware.Camera; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.util.Log; import android.view.Menu; import android.view.View; import android.view.WindowManager; import android.widget.Button; import android.widget.EditText; import android.widget.Toast; import com.dev.devapi.api.SysApi; import com.github.faucamp.simplertmp.RtmpHandler; import net.ossrs.yasea.CameraItemData; import net.ossrs.yasea.SrsCameraView; import net.ossrs.yasea.SrsEncodeHandler; import net.ossrs.yasea.SrsPublisher; import net.ossrs.yasea.SrsRecordHandler; import java.io.IOException; import java.net.SocketException; import java.util.List; import java.util.Random; public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpListener, SrsRecordHandler.SrsRecordListener, SrsEncodeHandler.SrsEncodeListener { private static final String TAG = "MpLive"; public final static int RC_CAMERA = 100; private Button btnPublish; private Button btnSwitchCamera; private Button btnRecord; private Button btnSwitchEncoder; private Button btnPause; private SharedPreferences sp; // private String rtmpUrl = "rtmp://192.168.50.250/live/0"; private String rtmpUrl = "rtmp://61.169.135.146/live/abcd"; private String recPath = Environment.getExternalStorageDirectory().getPath() + "/test.mp4"; private SrsPublisher mPublisher; private SrsCameraView mCameraView; private int mWidth = 1920; private int mHeight = 1080; private boolean isPermissionGranted = false; private Handler mHandler; private int cameraId = 0; private List cameraData; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mHandler = new Handler(); SysApi.setCam3V3Enable(true); getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM); setContentView(R.layout.activity_main); // response screen rotation event setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); requestPermission(); } private void requestPermission() { //1. 检查是否已经有该权限 if (Build.VERSION.SDK_INT >= 23 && (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED)) { //2. 权限没有开启,请求权限 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_CAMERA); } else { //权限已经开启,做相应事情 isPermissionGranted = true; try { init(); } catch (Exception ex) { ex.printStackTrace(); } } } //3. 接收申请成功或者失败回调 @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == RC_CAMERA) { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { //权限被用户同意,做相应的事情 isPermissionGranted = true; try { init(); } catch (Exception ex) { ex.printStackTrace(); } } else { //权限被用户拒绝,做相应的事情 finish(); } } } private void init() { // restore data. sp = getSharedPreferences("MpLive", MODE_PRIVATE); rtmpUrl = sp.getString("rtmpUrl", rtmpUrl); // initialize url. final EditText efu = (EditText) findViewById(R.id.url); efu.setText(rtmpUrl); btnPublish = (Button) findViewById(R.id.publish); btnSwitchCamera = (Button) findViewById(R.id.swCam); btnRecord = (Button) findViewById(R.id.record); btnSwitchEncoder = (Button) findViewById(R.id.swEnc); btnPause = (Button) findViewById(R.id.pause); btnPause.setEnabled(false); Intent intent = getIntent(); String url = intent.getStringExtra("url"); if (!TextUtils.isEmpty(url)) { rtmpUrl = url; } mCameraView = (SrsCameraView) findViewById(R.id.glsurfaceview_camera); // mCameraView.getHolder().addCallback(new SurfaceHolder.Callback() { // @Override // public void surfaceCreated(SurfaceHolder holder) { // Canvas canvas = holder.lockCanvas(); // if (canvas != null) { // canvas.drawColor(Color.WHITE); // canvas.rotate(45, canvas.getWidth() / 2, canvas.getHeight() / 2); // // 在旋转后的Canvas上绘制内容 // holder.unlockCanvasAndPost(canvas); // } // } // // @Override // public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { // // } // // @Override // public void surfaceDestroyed(SurfaceHolder holder) { // // } // }); int rotation = intent.getIntExtra("rotation", -1); if (rotation != -1) { //设置图像显示方向 mCameraView.setPreviewOrientation(rotation); } cameraData = mCameraView.getCameraData(); int size = cameraData.size(); if (size == 0) { Toast.makeText(getApplicationContext(), "没有查询到摄像头", Toast.LENGTH_SHORT).show(); } mPublisher = new SrsPublisher(mCameraView); mPublisher.setEncodeHandler(new SrsEncodeHandler(this)); mPublisher.setRtmpHandler(new RtmpHandler(this)); mPublisher.setRecordHandler(new SrsRecordHandler(this)); mPublisher.setPreviewResolution(mWidth, mHeight);//设置预览宽高 mPublisher.setOutputResolution(mHeight, mWidth); // 这里要和preview反过来 mPublisher.setVideoHDMode(); if (intent.hasExtra("cameraId")) { cameraId = intent.getIntExtra("cameraId", 0); mPublisher.switchCameraFace(cameraId); } mPublisher.startCamera(); mCameraView.setCameraCallbacksHandler(new SrsCameraView.CameraCallbacksHandler() { @Override public void onCameraParameters(Camera.Parameters params) { //params.setFocusMode("custom-focus"); //params.setWhiteBalance("custom-balance"); //etc... Log.e("fsfs", "fsdf"); } }); int autoStart = intent.getIntExtra("autoStart", 0); if (autoStart != 0) { mHandler.postDelayed(new Runnable() { @Override public void run() { btnPublish.performClick(); } }, 500); } int autoClose = intent.getIntExtra("autoClose", 0); if (autoClose != 0) { mHandler.postDelayed(new Runnable() { @Override public void run() { Log.w(TAG, "Close self automatically"); finish(); System.exit(0); } }, 1000); } btnPublish.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (btnPublish.getText().toString().contentEquals("publish")) { rtmpUrl = efu.getText().toString(); SharedPreferences.Editor editor = sp.edit(); editor.putString("rtmpUrl", rtmpUrl); editor.apply(); mPublisher.startPublish(rtmpUrl); mPublisher.startCamera(); if (btnSwitchEncoder.getText().toString().contentEquals("soft encoder")) { Toast.makeText(getApplicationContext(), "Use hard encoder", Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getApplicationContext(), "Use soft encoder", Toast.LENGTH_SHORT).show(); } btnPublish.setText("stop"); btnSwitchEncoder.setEnabled(false); btnPause.setEnabled(true); } else if (btnPublish.getText().toString().contentEquals("stop")) { mPublisher.stopPublish(); mPublisher.stopRecord(); btnPublish.setText("publish"); btnRecord.setText("record"); btnSwitchEncoder.setEnabled(true); btnPause.setEnabled(false); } } }); btnPause.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { if (btnPause.getText().toString().equals("Pause")) { mPublisher.pausePublish(); btnPause.setText("resume"); } else { mPublisher.resumePublish(); btnPause.setText("Pause"); } } }); btnSwitchCamera.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int size = cameraData.size(); if (size > 0) { int i = (++cameraId) % size; mPublisher.switchCameraFace(i); } } }); btnRecord.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (btnRecord.getText().toString().contentEquals("record")) { if (mPublisher.startRecord(recPath)) { btnRecord.setText("pause"); } } else if (btnRecord.getText().toString().contentEquals("pause")) { mPublisher.pauseRecord(); btnRecord.setText("resume"); } else if (btnRecord.getText().toString().contentEquals("resume")) { mPublisher.resumeRecord(); btnRecord.setText("pause"); } } }); btnSwitchEncoder.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (btnSwitchEncoder.getText().toString().contentEquals("soft encoder")) { mPublisher.switchToSoftEncoder(); btnSwitchEncoder.setText("hard encoder"); } else if (btnSwitchEncoder.getText().toString().contentEquals("hard encoder")) { mPublisher.switchToHardEncoder(); btnSwitchEncoder.setText("soft encoder"); } } }); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override protected void onStart() { super.onStart(); // if(mPublisher.getCamera() == null && isPermissionGranted){ // //if the camera was busy and available again // mPublisher.startCamera(); // } } @Override protected void onResume() { super.onResume(); final Button btn = (Button) findViewById(R.id.publish); btn.setEnabled(true); mPublisher.resumeRecord(); } @Override protected void onPause() { super.onPause(); mPublisher.pauseRecord(); } @Override protected void onDestroy() { super.onDestroy(); mPublisher.stopPublish(); mPublisher.stopRecord(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); mPublisher.stopEncode(); mPublisher.stopRecord(); btnRecord.setText("record"); mPublisher.setScreenOrientation(newConfig.orientation); if (btnPublish.getText().toString().contentEquals("stop")) { mPublisher.startEncode(); } mPublisher.startCamera(); } private static String getRandomAlphaString(int length) { String base = "abcdefghijklmnopqrstuvwxyz"; Random random = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); } private static String getRandomAlphaDigitString(int length) { String base = "abcdefghijklmnopqrstuvwxyz0123456789"; Random random = new Random(); StringBuilder sb = new StringBuilder(); for (int i = 0; i < length; i++) { int number = random.nextInt(base.length()); sb.append(base.charAt(number)); } return sb.toString(); } private void handleException(Exception e) { try { Toast.makeText(getApplicationContext(), e.getMessage(), Toast.LENGTH_SHORT).show(); mPublisher.stopPublish(); mPublisher.stopRecord(); btnPublish.setText("publish"); btnRecord.setText("record"); btnSwitchEncoder.setEnabled(true); } catch (Exception e1) { // } } // Implementation of SrsRtmpListener. @Override public void onRtmpConnecting(String msg) { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } @Override public void onRtmpConnected(String msg) { Toast.makeText(getApplicationContext(), msg, Toast.LENGTH_SHORT).show(); } @Override public void onRtmpVideoStreaming() { } @Override public void onRtmpAudioStreaming() { } @Override public void onRtmpStopped() { Toast.makeText(getApplicationContext(), "Stopped", Toast.LENGTH_SHORT).show(); } @Override public void onRtmpDisconnected() { Toast.makeText(getApplicationContext(), "Disconnected", Toast.LENGTH_SHORT).show(); } @Override public void onRtmpVideoFpsChanged(double fps) { Log.i(TAG, String.format("Output Fps: %f", fps)); } @Override public void onRtmpVideoBitrateChanged(double bitrate) { int rate = (int) bitrate; if (rate / 1000 > 0) { Log.i(TAG, String.format("Video bitrate: %f kbps", bitrate / 1000)); } else { Log.i(TAG, String.format("Video bitrate: %d bps", rate)); } } @Override public void onRtmpAudioBitrateChanged(double bitrate) { int rate = (int) bitrate; if (rate / 1000 > 0) { Log.i(TAG, String.format("Audio bitrate: %f kbps", bitrate / 1000)); } else { Log.i(TAG, String.format("Audio bitrate: %d bps", rate)); } } @Override public void onRtmpSocketException(SocketException e) { handleException(e); } @Override public void onRtmpIOException(IOException e) { handleException(e); } @Override public void onRtmpIllegalArgumentException(IllegalArgumentException e) { handleException(e); } @Override public void onRtmpIllegalStateException(IllegalStateException e) { handleException(e); } // Implementation of SrsRecordHandler. @Override public void onRecordPause() { Toast.makeText(getApplicationContext(), "Record paused", Toast.LENGTH_SHORT).show(); } @Override public void onRecordResume() { Toast.makeText(getApplicationContext(), "Record resumed", Toast.LENGTH_SHORT).show(); } @Override public void onRecordStarted(String msg) { Toast.makeText(getApplicationContext(), "Recording file: " + msg, Toast.LENGTH_SHORT).show(); } @Override public void onRecordFinished(String msg) { Toast.makeText(getApplicationContext(), "MP4 file saved: " + msg, Toast.LENGTH_SHORT).show(); } @Override public void onRecordIOException(IOException e) { handleException(e); } @Override public void onRecordIllegalArgumentException(IllegalArgumentException e) { handleException(e); } // Implementation of SrsEncodeHandler. @Override public void onNetworkWeak() { Toast.makeText(getApplicationContext(), "Network weak", Toast.LENGTH_SHORT).show(); } @Override public void onNetworkResume() { Toast.makeText(getApplicationContext(), "Network resume", Toast.LENGTH_SHORT).show(); } @Override public void onEncodeIllegalArgumentException(IllegalArgumentException e) { handleException(e); } }