自己主播


//跳转到直播源
--------
package com.bawei.myjufan;
import android.content.res.Configuration;
import android.opengl.GLSurfaceView;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Surface;
import android.view.View;
import android.widget.Button;
import android.widget.SeekBar;
import android.widget.Toast;

import com.bawei.myjufan.utils.SharedPreUtil;

import cn.nodemedia.LivePublisher;
import cn.nodemedia.LivePublisherDelegate;

/**
 * 直播推流实例
 */
public class LivePublisherDemoActivity extends AppCompatActivity implements View.OnClickListener, LivePublisherDelegate {
    private GLSurfaceView glsv;
    private Button micBtn, swtBtn, videoBtn, flashBtn, camBtn;
    private SeekBar mLevelSB;
    private boolean isStarting = false;
    private boolean isMicOn = true;
    private boolean isCamOn = true;
    private boolean isFlsOn = true;

    private Button capBtn;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_live_publisher_demo);
        isStarting = false;
        glsv = (GLSurfaceView) findViewById(R.id.camera_preview);
        micBtn = (Button) findViewById(R.id.button_mic);
        swtBtn = (Button) findViewById(R.id.button_sw);
        videoBtn = (Button) findViewById(R.id.button_video);
        flashBtn = (Button) findViewById(R.id.button_flash);
        camBtn = (Button) findViewById(R.id.button_cam);
        capBtn = (Button) findViewById(R.id.pub_cap_button);
        mLevelSB = (SeekBar) findViewById(R.id.pub_level_seekBar);

        micBtn.setOnClickListener(this);
        swtBtn.setOnClickListener(this);
        videoBtn.setOnClickListener(this);
        flashBtn.setOnClickListener(this);
        camBtn.setOnClickListener(this);
        capBtn.setOnClickListener(this);

        mLevelSB.setMax(5);
        mLevelSB.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
                // TODO Auto-generated method stub

            }

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                LivePublisher.setSmoothSkinLevel(progress);
            }
        });
        LivePublisher.init(this); // 1.初始化
        LivePublisher.setDelegate(this); // 2.设置事件回调

        /**
         * 设置输出音频参数 bitrate 码率 32kbps aacProfile 音频编码复杂度
         * 部分服务端不支持HE-AAC,会导致发布失败,如果服务端支持,直接用HE-AAC AAC_PROFILE_LC 低复杂度编码
         * AAC_PROFILE_HE 高效能编码 ,能达到LC-AAC一半的码率传输相同的音质
         */
        LivePublisher.setAudioParam(32 * 1000, LivePublisher.AAC_PROFILE_HE);

        /**
         * 设置输出视频参数
         * width 视频宽
         * height 视频高
         * 注意,视频最终输出的高宽和发布方向有关,这里设置 16:9的分辨率就行,sdk自动切换。
         *
         * fps 视频帧率
         * bitrate 视频码率 注意,sdk 1.0.1以后,视频码率为最大码率,可以比以前的版本值高一点,编码器自动调节
         * avcProfile 视频编码复杂度,高中低为三者比较相对而言。可根据应用场景选择
         * AVC_PROFILE_BASELINE 低CPU,低画质
         * AVC_PROFILE_MAIN 中CPU,中画质
         * AVC_PROFILE_HIGH 高CPU,高画质
         *
         * 以下建议分辨率及比特率 不用超过1280x720
         * 320X180@15 ~~ 300kbps ~~ baseline
         * 568x320@15 ~~ 400kbps ~~ baseline
         * 640X360@15 ~~ 500kbps ~~ main
         * 854x480@15 ~~ 600kbps ~~ main
         * 960x540@15 ~~ 800kbps ~~ high
         * 1280x720@15 ~~ 1000kbps ~~ high
         */
        LivePublisher.setVideoParam(640, 360, 15, 500 * 1000, LivePublisher.AVC_PROFILE_MAIN);

        /**
         * 是否开启背景噪音抑制
         */
        LivePublisher.setDenoiseEnable(true);

        /**
         * 设置美颜等级 0-5 0就关,5最高,可随时改动
         */
        LivePublisher.setSmoothSkinLevel(0);

        /**
         * 设置关键帧间隔 单位秒 默认1 gop_size = fps * keyFrameInterval
         * 注意,低关键帧间隔可以使得播放端快速显示画面,sdk默认每秒一个关键帧
         * 提高关键帧间隔可以提供更高的数据压缩比,节省部分网络带宽
         */
        // LivePublisher.setKeyFrameInterval(2);

        /**
         * 开始视频预览 cameraPreview : 用以回显摄像头预览的GLSurfaceView对象,如果此参数传入null,则只发布音频
         * 注意,如果做纯音频应用,请保证xml布局文件里不要放入GLSurfaceView控件,否则由于没有处理GLSurfaceView的渲染器会照成崩溃
         *
         * camId: 摄像头初始id,LivePublisher.CAMERA_BACK 后置,LivePublisher.CAMERA_FRONT 前置
         * frontMirror: 是否启用前置摄像头镜像模式。当为true时,预览画面为镜像画面。当为false时,预览画面为原始画面
         * 镜像画面就是平时使用系统照相机切换前置摄像头时所显示的画面,就像自己照镜子看到的画面。 原始画面就是最终保存或传输到观看者所显示的画面。
         */
        LivePublisher.startPreview(glsv, LivePublisher.CAMERA_FRONT, true);

    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        // 界面方向改变,通知sdk调整摄像头方向和视频方向
        // 注意:如果你的业务方案需求只做单一方向的视频直播,可以不处理这段

        // 如果程序UI没有锁定屏幕方向,旋转手机后,请把新的界面方向传入,以调整摄像头预览方向
        LivePublisher.setCameraOrientation(getWindowManager().getDefaultDisplay().getRotation());

        // 还没有开始发布视频的时候,可以跟随界面旋转的方向设置视频与当前界面方向一致,但一经开始发布视频,视频发布方向就锁定了
        // 发布中旋转只会让预览界面跟随旋转,当停止发布后再开始发布,新的流视频方向就与界面方向一致了
        switch (getWindowManager().getDefaultDisplay().getRotation()) {
            case Surface.ROTATION_0:
                LivePublisher.setVideoOrientation(LivePublisher.VIDEO_ORI_PORTRAIT);
                break;
            case Surface.ROTATION_90:
                LivePublisher.setVideoOrientation(LivePublisher.VIDEO_ORI_LANDSCAPE);
                break;
            case Surface.ROTATION_180:
                LivePublisher.setVideoOrientation(LivePublisher.VIDEO_ORI_PORTRAIT_REVERSE);
                break;
            case Surface.ROTATION_270:
                LivePublisher.setVideoOrientation(LivePublisher.VIDEO_ORI_LANDSCAPE_REVERSE);
                break;
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        LivePublisher.stopPublish();//停止发布
        LivePublisher.stopPreview();//停止预览
    }

    @Override
    public void onClick(View arg0) {
        switch (arg0.getId()) {
            case R.id.pub_cap_button:
                String capFilePath = Environment.getExternalStorageDirectory().getPath() + "/pub_cap.jpg";
                LivePublisher.capturePicture(capFilePath);

                break;
            case R.id.button_mic:
                if (isStarting) {
                    isMicOn = !isMicOn;
                    LivePublisher.setMicEnable(isMicOn); // 设置是否打开麦克风
                    if (isMicOn) {
                        handler.sendEmptyMessage(3101);
                    } else {
                        handler.sendEmptyMessage(3100);
                    }
                }
                break;
            case R.id.button_sw:
                LivePublisher.switchCamera();// 切换前后摄像头
                LivePublisher.setFlashEnable(false);// 关闭闪光灯,前置不支持闪光灯
                isFlsOn = false;
                flashBtn.setBackgroundResource(R.mipmap.ic_flash_off);
                break;
            case R.id.button_video:
                if (isStarting) {
                    LivePublisher.stopPublish();// 停止发布
                } else {
                    /**
                     * 设置视频发布的方向,此方法为可选,如果不调用,则输出视频方向跟随界面方向,如果特定指出视频方向,
                     * 在startPublish前调用设置 videoOrientation : 视频方向
                     * VIDEO_ORI_PORTRAIT           home键在 下 的 9:16 竖屏方向
                     * VIDEO_ORI_LANDSCAPE          home键在 右 的 16:9 横屏方向
                     * VIDEO_ORI_PORTRAIT_REVERSE   home键在 上 的 9:16 竖屏方向
                     * VIDEO_ORI_LANDSCAPE_REVERSE  home键在 左 的 16:9 横屏方向
                     */
                    // LivePublisher.setVideoOrientation(LivePublisher.VIDEO_ORI_LANDSCAPE);

                    /**
                     * 设置发布模式 参考 rtmp_specification_1.0.pdf 7.2.2.6. publish
                     * LivePublisher。PUBLISH_TYPE_LIVE 'live' 发布类型
                     * LivePublisher。PUBLISH_TYPE_RECORD 'record' 发布类型
                     * LivePublisher。PUBLISH_TYPE_APPEND 'append' 发布类型
                     */
                    // LivePublisher.setPublishType(LivePublisher.PUBLISH_TYPE_RECORD);

                    /**
                     * 开始视频发布 rtmpUrl rtmp流地址
                     */
                    String pubUrl ="rtmp://4335.livepush.myqcloud.com/live/4335_609711c37e4911e69776e435c87f075e?bizid=4335";
                    LivePublisher.startPublish(pubUrl);
                }
                break;
            case R.id.button_flash:
                int ret = -1;
                if (isFlsOn) {
                    ret = LivePublisher.setFlashEnable(false);
                } else {
                    ret = LivePublisher.setFlashEnable(true);
                }
                if (ret == -1) {
                    // 无闪光灯,或处于前置摄像头,不支持闪光灯操作
                } else if (ret == 0) {
                    // 闪光灯被关闭
                    flashBtn.setBackgroundResource(R.mipmap.ic_flash_off);
                    isFlsOn = false;
                } else {
                    // 闪光灯被打开
                    flashBtn.setBackgroundResource(R.mipmap.ic_flash_on);
                    isFlsOn = true;
                }
                break;
            case R.id.button_cam:
                if (isStarting) {
                    isCamOn = !isCamOn;
                    LivePublisher.setCamEnable(isCamOn);
                    if (isCamOn) {
                        handler.sendEmptyMessage(3103);
                    } else {
                        handler.sendEmptyMessage(3102);
                    }
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void onEventCallback(int event, String msg) {
        handler.sendEmptyMessage(event);
    }

    private Handler handler = new Handler() {
        // 回调处理
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case 2000:
                    Toast.makeText(LivePublisherDemoActivity.this, "正在发布视频", Toast.LENGTH_SHORT).show();
                    break;
                case 2001:
                    Toast.makeText(LivePublisherDemoActivity.this, "视频发布成功", Toast.LENGTH_SHORT).show();
                    videoBtn.setBackgroundResource(R.mipmap.ic_video_start);
                    isStarting = true;
                    break;
                case 2002:
                    Toast.makeText(LivePublisherDemoActivity.this, "视频发布失败", Toast.LENGTH_SHORT).show();
                    break;
                case 2004:
                    Toast.makeText(LivePublisherDemoActivity.this, "视频发布结束", Toast.LENGTH_SHORT).show();
                    videoBtn.setBackgroundResource(R.mipmap.ic_video_stop);
                    isStarting = false;
                    break;
                case 2005:
                    Toast.makeText(LivePublisherDemoActivity.this, "网络异常,发布中断", Toast.LENGTH_SHORT).show();
                    break;
                case 2100:
                    // 发布端网络阻塞,已缓冲了2秒的数据在队列中
                    Toast.makeText(LivePublisherDemoActivity.this, "网络阻塞,发布卡顿", Toast.LENGTH_SHORT).show();
                    break;
                case 2101:
                    // 发布端网络恢复畅通
                    Toast.makeText(LivePublisherDemoActivity.this, "网络恢复,发布流畅", Toast.LENGTH_SHORT).show();
                    break;
                case 2102:
                    Toast.makeText(LivePublisherDemoActivity.this, "截图保存成功", Toast.LENGTH_SHORT).show();
                    break;
                case 2103:
                    Toast.makeText(LivePublisherDemoActivity.this, "截图保存失败", Toast.LENGTH_SHORT).show();
                    break;
                case 3100:
                    // mic off
                    micBtn.setBackgroundResource(R.mipmap.ic_mic_off);
                    Toast.makeText(LivePublisherDemoActivity.this, "麦克风静音", Toast.LENGTH_SHORT).show();
                    break;
                case 3101:
                    // mic on
                    micBtn.setBackgroundResource(R.mipmap.ic_mic_on);
                    Toast.makeText(LivePublisherDemoActivity.this, "麦克风恢复", Toast.LENGTH_SHORT).show();
                    break;
                case 3102:
                    // camera off
                    camBtn.setBackgroundResource(R.mipmap.ic_cam_off);
                    Toast.makeText(LivePublisherDemoActivity.this, "摄像头传输关闭", Toast.LENGTH_SHORT).show();
                    break;
                case 3103:
                    // camera on
                    camBtn.setBackgroundResource(R.mipmap.ic_cam_on);
                    Toast.makeText(LivePublisherDemoActivity.this, "摄像头传输打开", Toast.LENGTH_SHORT).show();
                    break;
                default:
                    break;
            }
        }
    };
}
import java.util.Map;

import android.content.Context;
import android.content.SharedPreferences;

/**
 * 使用SharedPreferences存储数据 Created by Bining on 15/12/2.
 */
/**
 * 作者: 杨东海
 * 创建时间: 2016-9-19.
 */
public class SharedPreUtil {
    private static SharedPreferences getSharedPreferences(Context context) {
        return context.getSharedPreferences(SharedPreUtil.class.getSimpleName(), 0);
    }

    private static SharedPreferences.Editor getEdit(Context context) {
        return getSharedPreferences(context).edit();
    }

    public static void put(Context context, String key, Object object) {
        SharedPreferences.Editor editor = getEdit(context);
        if (object instanceof String) {
            editor.putString(key, (String) object);
        } else if (object instanceof Integer) {
            editor.putInt(key, (Integer) object);
        } else if (object instanceof Boolean) {
            editor.putBoolean(key, (Boolean) object);
        } else if (object instanceof Float) {
            editor.putFloat(key, (Float) object);
        } else if (object instanceof Long) {
            editor.putLong(key, (Long) object);
        } else if (object instanceof String[]) {
            StringBuilder datas = new StringBuilder();
            String[] data = (String[]) object;

            for (int i = 0; i < data.length; ++i) {
                if (i != 0) {
                    datas.append(":");
                }

                datas.append(data[i]);
            }
            editor.putString(key, datas.toString());
        }

        editor.commit();
    }

    public static String getString(Context context, String key,String defaultObject) {
        return getSharedPreferences(context).getString(key, defaultObject);
    }

    public static String getString(Context context, String key) {
        return getSharedPreferences(context).getString(key, "");
    }

    public static int getInt(Context context, String key) {
        return getSharedPreferences(context).getInt(key, 0);
    }

    public static boolean getBoolean(Context context, String key) {
        return getSharedPreferences(context).getBoolean(key, true);
    }

    public static float getFloat(Context context, String key) {
        return getSharedPreferences(context).getFloat(key, 0f);
    }

    public static long getLong(Context context, String key) {
        return getSharedPreferences(context).getLong(key, 0l);
    }

    public static String[] getStringArray(Context context, String key) {
        return getString(context, key).split(":");
    }

    public static void remove(Context context, String key) {
        SharedPreferences.Editor editor = getEdit(context);
        editor.remove(key);
        editor.commit();
    }

    public static void clear(Context context) {
        SharedPreferences.Editor editor = getEdit(context);
        editor.clear();
        editor.commit();
    }

    public static boolean contains(Context context, String key) {
        return getSharedPreferences(context).contains(key);
    }

    public static Map<String, ?> getAll(Context context) {
        return getSharedPreferences(context).getAll();
    }
}

//清单文件配置

   <activity
            android:name=".LivePublisherDemoActivity"
            android:configChanges="orientation|screenSize"
            android:theme="@style/Theme.AppCompat.NoActionBar">
        </activity>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值