Compare commits

..

11 Commits

Author SHA1 Message Date
liuguijing a39804142c Update version to 1.0.6 6 days ago
liuguijing 0212be3396 界面调整 6 days ago
liuguijing f7da5c3f6f 代码完善 2 weeks ago
liuguijing 7c2b5e0911 rtsp适配控制 4 weeks ago
liuguijing 55cab57cdc 开启rtsp端口 2 months ago
liuguijing cc709a87c7 开启rtsp端口 2 months ago
liuguijing 4a71482346 修复视频流摄像头翻转的bug 2 months ago
liuguijing 27809fd87b 用服务启动尝试(不行) 2 months ago
liuguijing 81f2c074d2 Update version to 1.0.4 2 months ago
liuguijing e025d3bf8a mplive建立分支 2 months ago
liuguijing 280d470409 Camera2 删除rtmp服务 7 months ago

@ -139,11 +139,7 @@ void TcpClient::onSockConnect(const SockException &ex) {
std::string TcpClient::getIdentifier() const {
if (_id.empty()) {
static atomic<uint64_t> s_index { 0 };
#ifndef DISABLE_RTTI
_id = toolkit::demangle(typeid(*this).name()) + "-" + to_string(++s_index);
#else
_id = toolkit::demangle("TcpClient") + "-" + to_string(++s_index);
#endif
}
return _id;
}

@ -146,9 +146,7 @@ public:
try {
CLASS_FUNC_INVOKE(C, *ptr, Destory);
} catch (std::exception &ex){
#ifndef DISABLE_RTTI
onDestoryException(typeid(C), ex);
#endif
}
delete ptr;
});
@ -174,9 +172,7 @@ public:
try {
CLASS_FUNC_INVOKE(C, *ptr, Destory);
} catch (std::exception &ex){
#ifndef DISABLE_RTTI
onDestoryException(typeid(C), ex);
#endif
}
delete ptr;
});
@ -459,11 +455,7 @@ public:
throw std::invalid_argument("Any is empty");
}
if (safe && !is<T>()) {
#ifndef DISABLE_RTTI
throw std::invalid_argument("Any::get(): " + demangle(_type->name()) + " unable cast to " + demangle(typeid(T).name()));
#else
throw std::invalid_argument("Any::get(): " + demangle(_type->name()) + " unable cast");
#endif
}
return *((T *)_data.get());
}

@ -312,7 +312,7 @@ int start_main(int argc,char *argv[]) {
listen_ip = "0.0.0.0";
uint16_t shellPort = 0; // mINI::Instance()[Shell::kPort];
uint16_t rtspPort = 0; // mINI::Instance()[Rtsp::kPort];
uint16_t rtspPort = mINI::Instance()[Rtsp::kPort];
uint16_t rtspsPort = 0; // mINI::Instance()[Rtsp::kSSLPort];
uint16_t rtmpPort = mINI::Instance()[Rtmp::kPort];
uint16_t rtmpsPort = 0; // mINI::Instance()[Rtmp::kSSLPort];
@ -402,7 +402,7 @@ int start_main(int argc,char *argv[]) {
InfoL << "已启动http hook 接口";
try {
// rtsp服务器端口默认554 [AUTO-TRANSLATED:07937d81]
// rtsp服务器端口默 认554 [AUTO-TRANSLATED:07937d81]
// rtsp server, default port 554
if (rtspPort) { rtspSrv->start<RtspSession>(rtspPort, listen_ip); }
// rtsps服务器端口默认322 [AUTO-TRANSLATED:e8a9fd71]
@ -439,7 +439,7 @@ int start_main(int argc,char *argv[]) {
if (rtcPort) { rtcSrv_udp->start<WebRtcSession>(rtcPort, listen_ip);}
if (rtcTcpPort) { rtcSrv_tcp->start<WebRtcSession>(rtcTcpPort, listen_ip);}
#endif//defined(ENABLE_WEBRTC)
#if defined(ENABLE_SRT)

@ -226,11 +226,7 @@ toolkit::EventPoller::Ptr MediaSource::getOwnerPoller() {
if (listener) {
return listener->getOwnerPoller(*this);
}
#ifndef DISABLE_RTTI
throw std::runtime_error(toolkit::demangle(typeid(*this).name()) + "::getOwnerPoller failed: " + getUrl());
#else
throw std::runtime_error(toolkit::demangle("MediaSource") + "::getOwnerPoller failed: " + getUrl());
#endif
}
std::shared_ptr<MultiMediaSourceMuxer> MediaSource::getMuxer() const {

@ -80,11 +80,7 @@ public:
virtual bool close(MediaSource &sender) { return false; }
// 获取观看总人数,此函数一般强制重载 [AUTO-TRANSLATED:1da20a10]
// Get the total number of viewers, this function is generally forced to overload
#ifndef DISABLE_RTTI
virtual int totalReaderCount(MediaSource &sender) { throw NotImplemented(toolkit::demangle(typeid(*this).name()) + "::totalReaderCount not implemented"); }
#else
virtual int totalReaderCount(MediaSource &sender) { throw NotImplemented(toolkit::demangle("MediaSourceEvent") + "::totalReaderCount not implemented"); }
#endif
// 通知观看人数变化 [AUTO-TRANSLATED:bad89528]
// Notify the change in the number of viewers
virtual void onReaderChanged(MediaSource &sender, int size);
@ -96,11 +92,7 @@ public:
virtual float getLossRate(MediaSource &sender, TrackType type) { return -1; }
// 获取所在线程, 此函数一般强制重载 [AUTO-TRANSLATED:71c99afb]
// Get the current thread, this function is generally forced to overload
#ifndef DISABLE_RTTI
virtual toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) { throw NotImplemented(toolkit::demangle(typeid(*this).name()) + "::getOwnerPoller not implemented"); }
#else
virtual toolkit::EventPoller::Ptr getOwnerPoller(MediaSource &sender) { throw NotImplemented(toolkit::demangle(typeid(*this).name()) + "::getOwnerPoller not implemented"); }
#endif
// //////////////////////仅供MultiMediaSourceMuxer对象继承//////////////////////// [AUTO-TRANSLATED:6e810d1f]
// //////////////////////Only for MultiMediaSourceMuxer object inheritance////////////////////////

@ -3,7 +3,7 @@ apply plugin: 'com.android.application'
// 10,00,000 major-minor-build
def AppMajorVersion = 1
def AppMinorVersion = 0
def AppBuildNumber = 3
def AppBuildNumber = 6
def AppVersionName = AppMajorVersion + "." + AppMinorVersion + "." + AppBuildNumber
def AppVersionCode = AppMajorVersion * 100000 + AppMinorVersion * 1000 + AppBuildNumber
@ -13,15 +13,17 @@ android {
defaultConfig {
applicationId "com.xypower.mplive"
minSdkVersion 28
targetSdkVersion 30
minSdkVersion 21
targetSdkVersion 28
versionCode AppVersionCode
versionName AppVersionName
ndk {
abiFilters "armeabi-v7a", "arm64-v8a"
}
externalNativeBuild {
cmake {
cppFlags "-std=c++11 -frtti -fexceptions"
arguments "-DENABLE_API=on", "-DENABLE_API_STATIC_LIB=on", "-DENABLE_TESTS=off", "-DENABLE_HLS=on", "-DENABLE_PLAYER=off", "-DENABLE_SERVER_LIB=on"
arguments "-DENABLE_API=on", "-DENABLE_API_STATIC_LIB=on", "-DENABLE_TESTS=off", "-DENABLE_HLS", "-DENABLE_PLAYER=off", "-DENABLE_SERVER_LIB=on"
abiFilters "armeabi-v7a", "arm64-v8a"
}
}
@ -43,7 +45,7 @@ android {
signingConfig signingConfigs.config
}
}
externalNativeBuild {
cmake {
path file('src/main/cpp/CMakeLists.txt')
@ -69,7 +71,7 @@ android {
buildFeatures {
viewBinding true
}
ndkVersion "28.0.13004108"
}
dependencies {

@ -9,8 +9,11 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.FLASHLIGHT" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-feature android:name="android.hardware.camera.autofocus" />
<uses-permission android:name="android.permission.CAPTURE_VIDEO_OUTPUT" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-feature android:glEsVersion="0x00020000" android:required="true" />
<application

@ -11,8 +11,6 @@ project("mplive")
set(CMAKE_CXX_STANDARD 11)
add_definitions(-DENABLE_HLS=1)
#so
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libs_export/${ANDROID_ABI})
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/libs_export/${ANDROID_ABI})
@ -41,8 +39,6 @@ include_directories(${ZLMediaKit_Root}/3rdpart)
include_directories(${ZLMediaKit_Root}/3rdpart/media-server)
include_directories(${ZLMediaKit_Root}/3rdpart/ZLToolKit/src)
message(WARNING " include path: ${MK_LINK_LIBRARIES}")
#
file(GLOB JNI_src_list ${JNI_Root}/*.cpp ${JNI_Root}/*.h)
add_library(mplive SHARED ${JNI_src_list})

@ -14,13 +14,6 @@
#include "Thread/semaphore.h"
#include "Common/config.h"
#include "Player/MediaPlayer.h"
#include "Network/TcpServer.h"
#include "Network/sockutil.h"
#include "Http/HttpSession.h"
#include "Rtmp/RtmpSession.h"
#include "Rtsp/RtspSession.h"
#include "Rtmp/RtmpPusher.h"
#include "Pusher/MediaPusher.h"
#include "Extension/Frame.h"
using namespace std;
@ -171,89 +164,6 @@ JNIEXPORT void JNICALL JNI_OnUnload(JavaVM* vm, void* reserved){
extern int start_main(int argc,char *argv[]);
std::shared_ptr<TcpServer> startRtmpServer(uint16_t port) {
auto server = std::make_shared<TcpServer>();
server->start<RtmpSession>(port);
InfoL << "RTMP Server listening on port " << port;
return server;
}
std::shared_ptr<TcpServer> startRtspServer(uint16_t port) {
auto server = std::make_shared<TcpServer>();
if (port == 0)
{
port = 554;
}
server->start<RtspSession>(port);
InfoL << "RTSP Server listening on port " << port;
return server;
}
void startRtmpPushers(const std::string& url, const std::string& targetUrl) {
MediaInfo mediaInfo(url);
auto mediaSource = MediaSource::find(mediaInfo);
if (!mediaSource) {
// 文件不存在 [AUTO-TRANSLATED:f97c8ce8]
// File does not exist
WarnL << url << " not existed: ";
return;
}
auto poller = EventPollerPool::Instance().getPoller();
auto pusher = std::make_shared<MediaPusher>(mediaSource, poller);
std::weak_ptr<MediaSource> weak_src = mediaSource;
// src用完了可以直接置空防止main函数持有它(MP4Reader持有它即可) [AUTO-TRANSLATED:52e6393a]
// src is used up, can be set to empty directly, to prevent the main function from holding it (MP4Reader holds it)
mediaSource = nullptr;
std::weak_ptr<MediaPusher> weak_pusher = pusher;
pusher->setOnShutdown([poller, url, weak_pusher, weak_src](const SockException &ex) {
if (!weak_src.lock()) {
// 媒体注销导致的推流中断,不在重试推流 [AUTO-TRANSLATED:625b3e1a]
// Media cancellation causes push interruption, no retry push
WarnL << "MediaSource released:" << ex << ", publish stopped";
return;
}
WarnL << "Server connection is closed:" << ex << ", republish after 2 seconds";
// 重新推流, 2秒后重试 [AUTO-TRANSLATED:f8a261a3]
// Repush, retry after 2 seconds
poller->doDelayTask(2 * 1000, [weak_pusher, url]() {
if (auto strong_push = weak_pusher.lock()) {
strong_push->publish(url);
}
return 0;
});
});
// 设置发布结果处理逻辑 [AUTO-TRANSLATED:ce9de055]
// Set the publish result handling logic
pusher->setOnPublished([poller, weak_pusher, url](const SockException &ex) {
if (!ex) {
InfoL << "Publish success, please play with player:" << url;
return;
}
WarnL << "Publish fail:" << ex << ", republish after 2 seconds";
// 如果发布失败,就重试 [AUTO-TRANSLATED:b37fd4aa]
// If the publish fails, retry
poller->doDelayTask(2 * 1000, [weak_pusher, url]() {
if (auto strong_push = weak_pusher.lock()) {
strong_push->publish(url);
}
return 0;
});
});
pusher->publish(targetUrl);
}
static semaphore sem;
JNI_API(jboolean, startServer, jstring ini_dir){
string sd_path = stringFromJstring(env,ini_dir);
string ini_file = sd_path + "/zlmediakit.ini";
@ -265,28 +175,38 @@ JNI_API(jboolean, startServer, jstring ini_dir){
DebugL << "ini file:" << ini_file;
thread s_th([sd_path,ini_file,pem_file](){
Logger::Instance().add(std::make_shared<ConsoleChannel>("ConsoleChannel", LTrace));
// Load the configuration file
// initConfig();
// Initialize the event loop
EventPollerPool::Instance().setPoolSize(4);
// Start the RTMP server
auto rtmpSvr = startRtmpServer(1935);
auto rtspSvr = startRtspServer(554);
// Start the RTMP pushers
// startRtmpPushers("", "");
// Wait for the signal to exit
signal(SIGINT, [](int) { sem.post(); });
signal(SIGTERM, [](int) { sem.post(); });
sem.wait();
s_tread_id = pthread_self();
try {
//http根目录修改默认路径
mINI::Instance()[Http::kRootPath] = sd_path + "/httpRoot";
//mp4录制点播根目录修改默认路径
mINI::Instance()[Protocol::kMP4SavePath] = sd_path + "/httpRoot";
//hls根目录修改默认路径
mINI::Instance()[Protocol::kHlsSavePath] = sd_path + "/httpRoot";
//替换默认端口号(在配置文件未生成时有效)
mINI::Instance()["http.port"] = 8080;
mINI::Instance()["http.sslport"] = 8443;
mINI::Instance()["rtsp.port"] = 8554;
// mINI::Instance()["rtsp.port"] = 0;
mINI::Instance()["rtsp.sslport"] = 8332;
// mINI::Instance()["rtsp.sslport"] = 0;
mINI::Instance()["general.enableVhost"] = 0;
for (auto &pr : mINI::Instance()) {
//替换hook默认地址
replace(pr.second, "https://127.0.0.1/", "http://127.0.0.1:8080/");
}
//默认打开hook
mINI::Instance()["hook.enable"] = 0;
//默认打开http api调试
mINI::Instance()["api.apiDebug"] = 1;
int argc = 5;
const char *argv[] = {"", "-c", ini_file.data(), "-s", pem_file.data()};
start_main(argc, (char **) argv);
s_tread_id = 0;
} catch (std::exception &ex) {
WarnL << ex.what();
}
});
// static onceToken s_token([]{
@ -296,8 +216,17 @@ JNI_API(jboolean, startServer, jstring ini_dir){
return true;
};
extern semaphore g_zl_sem;
JNI_API(void, stopServer) {
sem.post();
g_zl_sem.post();
s_tread_id = 0;
#if 0
if(s_tread_id){
pthread_kill(s_tread_id, SIGINT);
s_tread_id = 0;
}
#endif
}
JNI_API(jlong, createMediaPlayer, jstring url, jobject callback){

@ -2,10 +2,8 @@ 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;
@ -43,19 +41,17 @@ import java.net.SocketException;
import java.util.List;
import java.util.Random;
public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpListener, SrsRecordHandler.SrsRecordListener, SrsEncodeHandler.SrsEncodeListener {
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://127.0.0.1/live/0";
private String recPath = Environment.getExternalStorageDirectory().getPath() + "/test.mp4";
@ -69,9 +65,14 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
private Handler mHandler;
private int cameraId = 0;
private List<CameraItemData> cameraData;
private int rotation;
private int autoClose;
private int autoStart;
private static final int DELAY_MILLIS = 600000; // 延迟5分钟
private int netCamera;
private EditText efu;
public static final String CUSTOM_ACTION = "com.xypower.mpapp.ACT_TP_M";
private int channel;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -81,25 +82,26 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
setContentView(R.layout.activity_main);
// 关键代码声明为前台可见Android 10+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
setTurnScreenOn(true); // 唤醒屏幕(即使无物理屏)
setShowWhenLocked(true); // 允许锁屏显示
}
// response screen rotation event
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR);
requestPermission();
Intent intent = getIntent();
int overtime = intent.getIntExtra("overtime", DELAY_MILLIS);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, overtime);
}
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)) {
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);
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.CAMERA, Manifest.permission.RECORD_AUDIO, Manifest.permission.WRITE_EXTERNAL_STORAGE}, RC_CAMERA);
} else {
//权限已经开启,做相应事情
isPermissionGranted = true;
@ -111,6 +113,12 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
}
}
private void init() {
initView();
initIntent();
initEvent();
}
//3. 接收申请成功或者失败回调
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
@ -131,120 +139,65 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
}
}
private void init() {
private void initIntent() {
Intent intent = getIntent();
final int autoStart = intent.getIntExtra("autoStart", 1);
final int netCamera = intent.getIntExtra("netCamera", 0);
final int vendor = intent.getIntExtra("vendor", 0);
final int disableLocalServer = intent.getIntExtra("disableLocalServer", 0);
final int rotation = intent.getIntExtra("rotation", -1);
int autoClose = intent.getIntExtra("autoClose", 0);
// restore data.
sp = getSharedPreferences("MpLive", MODE_PRIVATE);
// rtmpUrl = sp.getString("rtmpUrl", rtmpUrl);
// initialize url.
final EditText efu = (EditText) findViewById(R.id.url);
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);
mCameraView = (SrsCameraView) findViewById(R.id.glsurfaceview_camera);
autoStart = intent.getIntExtra("autoStart", 1);
String url = intent.getStringExtra("url");
if (!TextUtils.isEmpty(url)) {
rtmpUrl = url;
}
if (TextUtils.isEmpty(rtmpUrl)) {
rtmpUrl = "rtmp://127.0.0.1/live/0";
}
efu.setText(rtmpUrl);
rotation = intent.getIntExtra("rotation", -1);
if (autoStart != 0) {
cameraId = intent.getIntExtra("cameraId", 0);
if (disableLocalServer == 0) {
startRTMPServer();
}
}
autoClose = intent.getIntExtra("autoClose", 0);
if (netCamera != 0) {
netCamera = intent.getIntExtra("netCamera", 0);
} else {
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));
channel = intent.getIntExtra("channel", 0);
}
mPublisher.setPreviewResolution(mWidth, mHeight);//设置预览宽高
mPublisher.setOutputResolution(mHeight, mWidth); // 这里要和preview反过来
private void initView() {
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);
mPublisher.setVideoHDMode();
efu = (EditText) findViewById(R.id.url);
efu.setText(rtmpUrl);
cameraId = intent.getIntExtra("cameraId", 0);
// mPublisher.startCamera();
mCameraView = (SrsCameraView) findViewById(R.id.glsurfaceview_camera);
mCameraView.setCameraCallbacksHandler(new SrsCameraView.CameraCallbacksHandler() {
@Override
public void onCameraParameters(Camera.Parameters params) {
Log.e("fsfs", "fsdf");
}
});
if (autoStart != 0) {
mPublisher.switchCameraFace(cameraId, rotation);
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// rtmpUrl = "rtmp://61.169.135.146/live/0";
SharedPreferences.Editor editor = sp.edit();
editor.putString("rtmpUrl", rtmpUrl);
editor.apply();
efu.setText(rtmpUrl + "rotation= " + rotation + " cameraid=" + cameraId + " auto=" + autoStart);
// efu.setText(rtmpUrl + " cameraid=" + cameraId + " auto=" + autoStart);
efu.setText(rtmpUrl);
mPublisher.startPublish(rtmpUrl);
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);
}
}, 500);
} else {
mPublisher.switchCameraFace(cameraId, rotation);
}
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反过来
if (autoClose != 0) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Log.w(TAG, "Close self automatically");
finish();
System.exit(0);
}
}, 1000);
}
mPublisher.setVideoHDMode();
mCameraView.setCameraCallbacksHandler(new SrsCameraView.CameraCallbacksHandler() {
@Override
public void onCameraParameters(Camera.Parameters params) {
Log.e("fsfs", "fsdf");
}
});
btnPublish.setOnClickListener(new View.OnClickListener() {
@Override
@ -254,12 +207,8 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
Toast.makeText(getApplicationContext(), "没有正确的推送地址", Toast.LENGTH_SHORT).show();
return;
}
SharedPreferences.Editor editor = sp.edit();
editor.putString("rtmpUrl", rtmpUrl);
editor.apply();
efu.setText(rtmpUrl);
mPublisher.startPublish(rtmpUrl);
// mPublisher.startCamera();
mPublisher.switchCameraFace(cameraId, rotation);
if (btnSwitchEncoder.getText().toString().contentEquals("soft encoder")) {
@ -335,6 +284,64 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
});
}
private void initEvent() {
if (autoStart == 1) {
startRTMPServer();
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
// rtmpUrl = "rtsp://127.0.0.1:8554/live/7";
efu.setText(rtmpUrl + " rotation= " + rotation + " cameraid=" + cameraId + " auto=" + autoStart);
if (netCamera == 0) {
mPublisher.startPublish(rtmpUrl);
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);
mPublisher.switchCameraFace(cameraId, rotation);
} else {
sendStartPushBroadcast();
}
}
}, 500);
} else {
mPublisher.switchCameraFace(cameraId, rotation);
}
if (autoClose != 0) {
mHandler.postDelayed(new Runnable() {
@Override
public void run() {
Log.w(TAG, "Close self automatically");
finish();
System.exit(0);
}
}, 100000);
}
}
private void sendStartPushBroadcast() {
Log.d("开始发送广播", rtmpUrl);
Intent intent = new Intent(CUSTOM_ACTION);
intent.putExtra("Channel", channel);
intent.putExtra("MediaType", 16);
intent.putExtra("Url", rtmpUrl);
sendBroadcast(intent);
}
private void sendStopPushBroadcast() {
Intent intent = new Intent(CUSTOM_ACTION);
intent.putExtra("Channel", channel);
intent.putExtra("MediaType", 17);
intent.putExtra("Url", rtmpUrl);
sendBroadcast(intent);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
@ -419,8 +426,6 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
@Override
protected void onResume() {
super.onResume();
final Button btn = (Button) findViewById(R.id.publish);
btn.setEnabled(true);
mPublisher.resumeRecord();
}
@ -433,27 +438,32 @@ public class MainActivity extends AppCompatActivity implements RtmpHandler.RtmpL
@Override
protected void onDestroy() {
super.onDestroy();
// mPublisher.stopEncode();
if (netCamera == 1) {
sendStopPushBroadcast();
}
stopRTMPServer();
mPublisher.stopPublish();
mPublisher.stopRecord();
stopRTMPServer();
}
@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();
}
// @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 void startRTMPServer() {
File streamingDir = new File(getDataDir(), "streaming");
File streamingDir = null;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N) {
streamingDir = new File(getDataDir(), "streaming");
}
if (!streamingDir.exists()) {
streamingDir.mkdirs();
}

@ -7,7 +7,7 @@ buildscript {
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:7.2.1'
classpath 'com.android.tools.build:gradle:4.1.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files

@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.5-bin.zip
distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-6.5-all.zip

@ -193,7 +193,6 @@ public class RtmpConnection implements RtmpPublisher {
connectingLock.wait(5000);
} catch (InterruptedException ex) {
// do nothing
ex.printStackTrace();
}
}
if (!connected) {

@ -61,7 +61,34 @@ public class GPUImageFilter {
private int[] mGLFboId;
private int[] mGLFboTexId;
private IntBuffer mGLFboBuffer;
private float[] TEX_COORD;
final float TEX_COORD0[] = {
0.0f, 0.0f, // Bottom left.
1.0f, 0.0f, // Bottom right.
0.0f, 1.0f, // Top left.
1.0f, 1.0f // Top right.
};
final float TEX_COORD_90[] = {
0.0f, 1.0f, // Bottom left.
0.0f, 0.0f, // Bottom right.
1.0f, 1.0f, // Top left.
1.0f, 0.0f // Top right.
};
final float TEX_COORD_180[] = {
1.0f, 1.0f, // Bottom left.
0.0f, 1.0f, // Bottom right.
1.0f, 0.0f, // Top left.
0.0f, 0.0f // Top right.
};
final float TEX_COORD_270[] = {
1.0f, 0.0f, // Bottom left.
1.0f, 1.0f, // Bottom right.
0.0f, 0.0f, // Top left.
0.0f, 1.0f // Top right.
};
private float[] TEX_COORD = TEX_COORD0;
public GPUImageFilter() {
this(MagicFilterType.NONE);
@ -476,33 +503,6 @@ public class GPUImageFilter {
// 1.0f, 1.0f // Top right.
// };
final float TEX_COORD0[] = {
0.0f, 0.0f, // Bottom left.
1.0f, 0.0f, // Bottom right.
0.0f, 1.0f, // Top left.
1.0f, 1.0f // Top right.
};
final float TEX_COORD_90[] = {
0.0f, 1.0f, // Bottom left.
0.0f, 0.0f, // Bottom right.
1.0f, 1.0f, // Top left.
1.0f, 0.0f // Top right.
};
final float TEX_COORD_180[] = {
1.0f, 1.0f, // Bottom left.
0.0f, 1.0f, // Bottom right.
1.0f, 0.0f, // Top left.
0.0f, 0.0f // Top right.
};
final float TEX_COORD_270[] = {
1.0f, 0.0f, // Bottom left.
1.0f, 1.0f, // Bottom right.
0.0f, 0.0f, // Top left.
0.0f, 1.0f // Top right.
};
//纹理坐标
TEX_COORD = TEX_COORD0;
if (rotation == 0) {
TEX_COORD = TEX_COORD0;
} else if (rotation == 90) {

Loading…
Cancel
Save