package com.laifeng.sopcastdemo; import android.app.Activity; import android.app.Dialog; import android.content.DialogInterface; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.view.GestureDetector; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.widget.Button; import android.widget.EditText; import android.widget.ImageButton; import android.widget.ProgressBar; import android.widget.Toast; import com.laifeng.sopcastdemo.ui.MultiToggleImageButton; import com.laifeng.sopcastsdk.camera.CameraListener; import com.laifeng.sopcastsdk.configuration.AudioConfiguration; import com.laifeng.sopcastsdk.configuration.CameraConfiguration; import com.laifeng.sopcastsdk.configuration.VideoConfiguration; import com.laifeng.sopcastsdk.entity.Watermark; import com.laifeng.sopcastsdk.entity.WatermarkPosition; import com.laifeng.sopcastsdk.stream.packer.rtmp.RtmpPacker; import com.laifeng.sopcastsdk.stream.sender.rtmp.RtmpSender; import com.laifeng.sopcastsdk.ui.CameraLivingView; import com.laifeng.sopcastsdk.utils.SopCastLog; import com.laifeng.sopcastsdk.video.effect.GrayEffect; import com.laifeng.sopcastsdk.video.effect.NullEffect; import static com.laifeng.sopcastsdk.constant.SopCastConstant.TAG; public class LandscapeActivity extends Activity { private CameraLivingView mLFLiveView; private MultiToggleImageButton mMicBtn; private MultiToggleImageButton mFlashBtn; private MultiToggleImageButton mFaceBtn; private MultiToggleImageButton mBeautyBtn; private MultiToggleImageButton mFocusBtn; private GestureDetector mGestureDetector; private GrayEffect mGrayEffect; private NullEffect mNullEffect; private ImageButton mRecordBtn; private boolean isGray; private boolean isRecording; private ProgressBar mProgressConnecting; private RtmpSender mRtmpSender; private VideoConfiguration mVideoConfiguration; private int mCurrentBps; private Dialog mUploadDialog; private EditText mAddressET; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_landscape); initEffects(); initViews(); initListeners(); initLiveView(); initRtmpAddressDialog(); } private void initEffects() { mGrayEffect = new GrayEffect(this); mNullEffect = new NullEffect(this); } private void initViews() { mLFLiveView = (CameraLivingView) findViewById(R.id.liveView); mMicBtn = (MultiToggleImageButton) findViewById(R.id.record_mic_button); mFlashBtn = (MultiToggleImageButton) findViewById(R.id.camera_flash_button); mFaceBtn = (MultiToggleImageButton) findViewById(R.id.camera_switch_button); mBeautyBtn = (MultiToggleImageButton) findViewById(R.id.camera_render_button); mFocusBtn = (MultiToggleImageButton) findViewById(R.id.camera_focus_button); mRecordBtn = (ImageButton) findViewById(R.id.btnRecord); mProgressConnecting = (ProgressBar) findViewById(R.id.progressConnecting); } private void initListeners() { mMicBtn.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { @Override public void stateChanged(View view, int state) { mLFLiveView.mute(true); } }); mFlashBtn.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { @Override public void stateChanged(View view, int state) { mLFLiveView.switchTorch(); } }); mFaceBtn.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { @Override public void stateChanged(View view, int state) { mLFLiveView.switchCamera(); } }); mBeautyBtn.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { @Override public void stateChanged(View view, int state) { if(isGray) { mLFLiveView.setEffect(mNullEffect); isGray = false; } else { mLFLiveView.setEffect(mGrayEffect); isGray = true; } } }); mFocusBtn.setOnStateChangeListener(new MultiToggleImageButton.OnStateChangeListener() { @Override public void stateChanged(View view, int state) { mLFLiveView.switchFocusMode(); } }); mRecordBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if(isRecording) { mProgressConnecting.setVisibility(View.GONE); Toast.makeText(LandscapeActivity.this, "stop living", Toast.LENGTH_SHORT).show(); mRecordBtn.setBackgroundResource(R.mipmap.ic_record_start); mLFLiveView.stop(); isRecording = false; } else { mUploadDialog.show(); } } }); } private void initRtmpAddressDialog() { LayoutInflater inflater = getLayoutInflater(); View playView = inflater.inflate(R.layout.address_dialog,(ViewGroup) findViewById(R.id.dialog)); mAddressET = (EditText) playView.findViewById(R.id.address); Button okBtn = (Button) playView.findViewById(R.id.ok); Button cancelBtn = (Button) playView.findViewById(R.id.cancel); AlertDialog.Builder uploadBuilder = new AlertDialog.Builder(this); uploadBuilder.setTitle("Upload Address"); uploadBuilder.setView(playView); mUploadDialog = uploadBuilder.create(); okBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { String uploadUrl = mAddressET.getText().toString(); if(TextUtils.isEmpty(uploadUrl)) { Toast.makeText(LandscapeActivity.this, "Upload address is empty!", Toast.LENGTH_SHORT).show(); } else { mRtmpSender.setAddress(uploadUrl); mProgressConnecting.setVisibility(View.VISIBLE); Toast.makeText(LandscapeActivity.this, "start connecting", Toast.LENGTH_SHORT).show(); mRecordBtn.setBackgroundResource(R.mipmap.ic_record_stop); mRtmpSender.connect(); isRecording = true; } mUploadDialog.dismiss(); } }); cancelBtn.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mUploadDialog.dismiss(); } }); } private void initLiveView() { SopCastLog.isOpen(true); mLFLiveView.init(); CameraConfiguration.Builder cameraBuilder = new CameraConfiguration.Builder(); cameraBuilder.setOrientation(CameraConfiguration.Orientation.LANDSCAPE) .setFacing(CameraConfiguration.Facing.BACK); CameraConfiguration cameraConfiguration = cameraBuilder.build(); mLFLiveView.setCameraConfiguration(cameraConfiguration); VideoConfiguration.Builder videoBuilder = new VideoConfiguration.Builder(); videoBuilder.setSize(640, 360); mVideoConfiguration = videoBuilder.build(); mLFLiveView.setVideoConfiguration(mVideoConfiguration); //设置水印 Bitmap watermarkImg = BitmapFactory.decodeResource(getResources(), R.mipmap.watermark); Watermark watermark = new Watermark(watermarkImg, 50, 25, WatermarkPosition.WATERMARK_ORIENTATION_BOTTOM_RIGHT, 8, 8); mLFLiveView.setWatermark(watermark); //设置预览监听 mLFLiveView.setCameraOpenListener(new CameraListener() { @Override public void onOpenSuccess() { Toast.makeText(LandscapeActivity.this, "camera open success", Toast.LENGTH_LONG).show(); } @Override public void onOpenFail(int error) { Toast.makeText(LandscapeActivity.this, "camera open fail", Toast.LENGTH_LONG).show(); } @Override public void onCameraChange() { Toast.makeText(LandscapeActivity.this, "camera switch", Toast.LENGTH_LONG).show(); } }); //设置手势识别 mGestureDetector = new GestureDetector(this, new GestureListener()); mLFLiveView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { mGestureDetector.onTouchEvent(event); return false; } }); //初始化flv打包器 RtmpPacker packer = new RtmpPacker(); packer.initAudioParams(AudioConfiguration.DEFAULT_FREQUENCY, 16, false); mLFLiveView.setPacker(packer); //设置发送器 mRtmpSender = new RtmpSender(); mRtmpSender.setVideoParams(640, 360); mRtmpSender.setAudioParams(AudioConfiguration.DEFAULT_FREQUENCY, 16, false); mRtmpSender.setSenderListener(mSenderListener); mLFLiveView.setSender(mRtmpSender); mLFLiveView.setLivingStartListener(new CameraLivingView.LivingStartListener() { @Override public void startError(int error) { //直播失败 Toast.makeText(LandscapeActivity.this, "start living fail", Toast.LENGTH_SHORT).show(); mLFLiveView.stop(); } @Override public void startSuccess() { //直播成功 Toast.makeText(LandscapeActivity.this, "start living", Toast.LENGTH_SHORT).show(); } }); } private RtmpSender.OnSenderListener mSenderListener = new RtmpSender.OnSenderListener() { @Override public void onConnecting() { } @Override public void onConnected() { mProgressConnecting.setVisibility(View.GONE); mLFLiveView.start(); mCurrentBps = mVideoConfiguration.maxBps; } @Override public void onDisConnected() { mProgressConnecting.setVisibility(View.GONE); Toast.makeText(LandscapeActivity.this, "fail to live", Toast.LENGTH_SHORT).show(); mRecordBtn.setBackgroundResource(R.mipmap.ic_record_start); mLFLiveView.stop(); isRecording = false; } @Override public void onPublishFail() { mProgressConnecting.setVisibility(View.GONE); Toast.makeText(LandscapeActivity.this, "fail to publish stream", Toast.LENGTH_SHORT).show(); mRecordBtn.setBackgroundResource(R.mipmap.ic_record_start); isRecording = false; } @Override public void onNetGood() { if (mCurrentBps + 50 <= mVideoConfiguration.maxBps){ SopCastLog.d(TAG, "BPS_CHANGE good up 50"); int bps = mCurrentBps + 50; if(mLFLiveView != null) { boolean result = mLFLiveView.setVideoBps(bps); if(result) { mCurrentBps = bps; } } } else { SopCastLog.d(TAG, "BPS_CHANGE good good good"); } SopCastLog.d(TAG, "Current Bps: " + mCurrentBps); } @Override public void onNetBad() { if (mCurrentBps - 100 >= mVideoConfiguration.minBps){ SopCastLog.d(TAG, "BPS_CHANGE bad down 100"); int bps = mCurrentBps - 100; if(mLFLiveView != null) { boolean result = mLFLiveView.setVideoBps(bps); if(result) { mCurrentBps = bps; } } } else { SopCastLog.d(TAG, "BPS_CHANGE bad down 100"); } SopCastLog.d(TAG, "Current Bps: " + mCurrentBps); } }; public class GestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1.getX() - e2.getX() > 100 && Math.abs(velocityX) > 200) { // Fling left Toast.makeText(LandscapeActivity.this, "Fling Left", Toast.LENGTH_SHORT).show(); } else if (e2.getX() - e1.getX() > 100 && Math.abs(velocityX) > 200) { // Fling right Toast.makeText(LandscapeActivity.this, "Fling Right", Toast.LENGTH_SHORT).show(); } return super.onFling(e1, e2, velocityX, velocityY); } } @Override protected void onStop() { super.onStop(); mLFLiveView.pause(); } @Override protected void onStart() { super.onStart(); mLFLiveView.resume(); } @Override protected void onDestroy() { super.onDestroy(); mLFLiveView.stop(); mLFLiveView.release(); } }