Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
xuqlei
easyipcamera
提交
4d59186e
E
easyipcamera
项目概览
xuqlei
/
easyipcamera
与 Fork 源项目一致
从无法访问的项目Fork
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
E
easyipcamera
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
提交
4d59186e
编写于
2月 19, 2017
作者:
jinlong0603
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
更新最新的推送库,Android增加软编码及同屏功能
上级
f216f439
变更
47
展开全部
隐藏空白更改
内联
并排
Showing
47 changed file
with
1393 addition
and
331 deletion
+1393
-331
Android/.gitignore
Android/.gitignore
+2
-3
Android/.idea/.name
Android/.idea/.name
+0
-1
Android/.idea/gradle.xml
Android/.idea/gradle.xml
+1
-2
Android/app/build.gradle
Android/app/build.gradle
+3
-3
Android/app/libs/armeabi-v7a/libEasyIPCamera.so
Android/app/libs/armeabi-v7a/libEasyIPCamera.so
+0
-0
Android/app/libs/armeabi-v7a/libUtils.so
Android/app/libs/armeabi-v7a/libUtils.so
+0
-0
Android/app/libs/armeabi-v7a/libx264enc.so
Android/app/libs/armeabi-v7a/libx264enc.so
+0
-0
Android/app/libs/armeabi/libEasyIPCamera.so
Android/app/libs/armeabi/libEasyIPCamera.so
+0
-0
Android/app/src/main/AndroidManifest.xml
Android/app/src/main/AndroidManifest.xml
+10
-1
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/EasyApplication.java
...org/easydarwin/easyipcamera/activity/EasyApplication.java
+2
-2
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/RecordService.java
...a/org/easydarwin/easyipcamera/activity/RecordService.java
+420
-0
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/SettingActivity.java
...org/easydarwin/easyipcamera/activity/SettingActivity.java
+14
-1
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/SplashActivity.java
.../org/easydarwin/easyipcamera/activity/SplashActivity.java
+1
-1
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/StreameActivity.java
...org/easydarwin/easyipcamera/activity/StreameActivity.java
+160
-16
Android/app/src/main/java/org/easydarwin/easyipcamera/camera/AudioStream.java
.../java/org/easydarwin/easyipcamera/camera/AudioStream.java
+20
-10
Android/app/src/main/java/org/easydarwin/easyipcamera/camera/EasyIPCamera.java
...java/org/easydarwin/easyipcamera/camera/EasyIPCamera.java
+20
-4
Android/app/src/main/java/org/easydarwin/easyipcamera/camera/MediaStream.java
.../java/org/easydarwin/easyipcamera/camera/MediaStream.java
+346
-142
Android/app/src/main/java/org/easydarwin/easyipcamera/config/Config.java
.../main/java/org/easydarwin/easyipcamera/config/Config.java
+1
-1
Android/app/src/main/java/org/easydarwin/easyipcamera/hw/CodecManager.java
...ain/java/org/easydarwin/easyipcamera/hw/CodecManager.java
+1
-1
Android/app/src/main/java/org/easydarwin/easyipcamera/sw/JNIUtil.java
...src/main/java/org/easydarwin/easyipcamera/sw/JNIUtil.java
+61
-0
Android/app/src/main/java/org/easydarwin/easyipcamera/sw/X264Encoder.java
...main/java/org/easydarwin/easyipcamera/sw/X264Encoder.java
+66
-0
Android/app/src/main/java/org/easydarwin/easyipcamera/util/Util.java
.../src/main/java/org/easydarwin/easyipcamera/util/Util.java
+70
-12
Android/app/src/main/java/org/easydarwin/easyipcamera/view/StatusInfoView.java
...java/org/easydarwin/easyipcamera/view/StatusInfoView.java
+41
-4
Android/app/src/main/res/layout/activity_main.xml
Android/app/src/main/res/layout/activity_main.xml
+52
-52
Android/app/src/main/res/layout/activity_setting.xml
Android/app/src/main/res/layout/activity_setting.xml
+12
-3
Android/app/src/main/res/layout/activity_splash.xml
Android/app/src/main/res/layout/activity_splash.xml
+1
-1
Android/build.gradle
Android/build.gradle
+1
-1
Android/gradle.properties
Android/gradle.properties
+2
-2
Android/gradle/wrapper/gradle-wrapper.properties
Android/gradle/wrapper/gradle-wrapper.properties
+2
-2
EasyIPCamera_RTSP/libEasyRTSPClient/Include/EasyRTSPClientAPI.h
...Camera_RTSP/libEasyRTSPClient/Include/EasyRTSPClientAPI.h
+5
-1
EasyIPCamera_RTSP/libEasyRTSPClient/Lib/libEasyRTSPClient.dll
...IPCamera_RTSP/libEasyRTSPClient/Lib/libEasyRTSPClient.dll
+0
-0
EasyIPCamera_RTSP/libEasyRTSPClient/Lib/libEasyRTSPClient.lib
...IPCamera_RTSP/libEasyRTSPClient/Lib/libEasyRTSPClient.lib
+0
-0
EasyIPCamera_RTSP/main.cpp
EasyIPCamera_RTSP/main.cpp
+19
-5
EasyIPCamera_Win/ServerManager.cpp
EasyIPCamera_Win/ServerManager.cpp
+1
-1
Include/EasyTypes.h
Include/EasyTypes.h
+59
-59
Lib/hisiv100/libeasyipcamera.a
Lib/hisiv100/libeasyipcamera.a
+0
-0
Lib/hisiv100_shared/libeasyipcamera.so
Lib/hisiv100_shared/libeasyipcamera.so
+0
-0
Lib/hisiv200/libeasyipcamera.a
Lib/hisiv200/libeasyipcamera.a
+0
-0
Lib/hisiv200_shared/libeasyipcamera.so
Lib/hisiv200_shared/libeasyipcamera.so
+0
-0
Lib/hisiv300/libeasyipcamera.a
Lib/hisiv300/libeasyipcamera.a
+0
-0
Lib/hisiv300_shared/libeasyipcamera.so
Lib/hisiv300_shared/libeasyipcamera.so
+0
-0
Lib/hisiv400/libeasyipcamera.a
Lib/hisiv400/libeasyipcamera.a
+0
-0
Lib/hisiv400_shared/libeasyipcamera.so
Lib/hisiv400_shared/libeasyipcamera.so
+0
-0
Lib/i386/libeasyipcamera.a
Lib/i386/libeasyipcamera.a
+0
-0
Lib/libEasyIPCamera.dll
Lib/libEasyIPCamera.dll
+0
-0
Lib/libEasyIPCamera.lib
Lib/libEasyIPCamera.lib
+0
-0
Lib/x64/libeasyipcamera.a
Lib/x64/libeasyipcamera.a
+0
-0
未找到文件。
Android/.gitignore
浏览文件 @
4d59186e
*.iml
.gradle
/.gradle
/.idea
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
Android/.idea/.name
已删除
100644 → 0
浏览文件 @
f216f439
Android
\ No newline at end of file
Android/.idea/gradle.xml
浏览文件 @
4d59186e
...
...
@@ -3,9 +3,8 @@
<component
name=
"GradleSettings"
>
<option
name=
"linkedExternalProjectsSettings"
>
<GradleProjectSettings>
<option
name=
"distributionType"
value=
"
LOCAL
"
/>
<option
name=
"distributionType"
value=
"
DEFAULT_WRAPPED
"
/>
<option
name=
"externalProjectPath"
value=
"$PROJECT_DIR$"
/>
<option
name=
"gradleHome"
value=
"F:\01Tools\Android\android-studio\gradle\gradle-2.10"
/>
<option
name=
"modules"
>
<set>
<option
value=
"$PROJECT_DIR$"
/>
...
...
Android/app/build.gradle
浏览文件 @
4d59186e
...
...
@@ -7,9 +7,9 @@ android {
defaultConfig
{
applicationId
"org.easydarwin.easyipcamera"
minSdkVersion
16
targetSdkVersion
2
3
versionCode
1
versionName
"1.
0.16.092
9"
targetSdkVersion
2
1
versionCode
4
versionName
"1.
2.17.021
9"
}
buildTypes
{
release
{
...
...
Android/app/libs/armeabi-v7a/libEasyIPCamera.so
浏览文件 @
4d59186e
无法预览此类型文件
Android/app/libs/armeabi-v7a/libUtils.so
0 → 100644
浏览文件 @
4d59186e
文件已添加
Android/app/libs/armeabi-v7a/libx264enc.so
0 → 100644
浏览文件 @
4d59186e
文件已添加
Android/app/libs/armeabi/libEasyIPCamera.so
已删除
100644 → 0
浏览文件 @
f216f439
文件已删除
Android/app/src/main/AndroidManifest.xml
浏览文件 @
4d59186e
...
...
@@ -11,6 +11,11 @@
<uses-feature
android:name=
"android.hardware.camera"
/>
<uses-permission
android:name=
"android.permission.ACCESS_NETWORK_STATE"
/>
<uses-permission
android:name=
"android.permission.ACCESS_WIFI_STATE"
/>
<uses-permission
android:name=
"android.permission.CHANGE_WIFI_STATE"
/>
<uses-permission
android:name=
"android.permission.WAKE_LOCK"
/>
<uses-permission
android:name=
"android.permission.INTERNET"
/>
<application
android:name=
".activity.EasyApplication"
android:allowBackup=
"true"
...
...
@@ -37,7 +42,11 @@
android:name=
".activity.StreameActivity"
android:screenOrientation=
"portrait"
/>
<receiver
android:name=
"org.easydarwin.easyipcamera.updatemgr.CompleteReceiver"
>
<service
android:name=
".activity.RecordService"
android:enabled=
"true"
/>
<receiver
android:name=
".updatemgr.CompleteReceiver"
>
<intent-filter>
<action
android:name=
"android.intent.action.DOWNLOAD_COMPLETE"
/>
<action
android:name=
"android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED"
/>
...
...
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/EasyApplication.java
浏览文件 @
4d59186e
/*
Copyright (c) 2012-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2012-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
...
...
@@ -30,7 +30,7 @@ public class EasyApplication extends Application {
mApplication
=
this
;
if
(
Util
.
getSupportResolution
(
this
).
size
()
==
0
)
{
StringBuilder
stringBuilder
=
new
StringBuilder
();
Camera
camera
=
Camera
.
open
();
Camera
camera
=
Camera
.
open
(
Camera
.
CameraInfo
.
CAMERA_FACING_BACK
);
List
<
Camera
.
Size
>
supportedPreviewSizes
=
camera
.
getParameters
().
getSupportedPreviewSizes
();
for
(
Camera
.
Size
str
:
supportedPreviewSizes
)
{
stringBuilder
.
append
(
str
.
width
+
"x"
+
str
.
height
).
append
(
";"
);
...
...
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/RecordService.java
0 → 100644
浏览文件 @
4d59186e
/*
Copyright (c) 2012-2016 EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
*/
package
org.easydarwin.easyipcamera.activity
;
import
android.annotation.TargetApi
;
import
android.app.Service
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.hardware.display.DisplayManager
;
import
android.hardware.display.VirtualDisplay
;
import
android.media.MediaCodec
;
import
android.media.MediaCodecInfo
;
import
android.media.MediaFormat
;
import
android.media.projection.MediaProjection
;
import
android.media.projection.MediaProjectionManager
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.os.Environment
;
import
android.os.IBinder
;
import
android.os.Process
;
import
android.support.annotation.Nullable
;
import
android.util.Base64
;
import
android.util.DisplayMetrics
;
import
android.util.Log
;
import
android.view.Surface
;
import
android.view.WindowManager
;
import
org.easydarwin.easyipcamera.camera.EasyIPCamera
;
import
org.easydarwin.easyipcamera.hw.EncoderDebugger
;
import
org.easydarwin.easyipcamera.util.Util
;
import
org.easydarwin.easyipcamera.view.StatusInfoView
;
import
java.io.IOException
;
import
java.nio.ByteBuffer
;
import
java.nio.ByteOrder
;
public
class
RecordService
extends
Service
implements
EasyIPCamera
.
IPCameraCallBack
{
private
static
final
String
TAG
=
"RecordService"
;
private
String
mVideoPath
;
private
MediaProjectionManager
mMpmngr
;
private
MediaProjection
mMpj
;
private
VirtualDisplay
mVirtualDisplay
;
private
int
windowWidth
;
private
int
windowHeight
;
private
int
screenDensity
;
private
Surface
mSurface
;
private
MediaCodec
mMediaCodec
;
private
WindowManager
wm
;
private
MediaCodec
.
BufferInfo
mBufferInfo
=
new
MediaCodec
.
BufferInfo
();
static
EasyIPCamera
mEasyIPCamera
;
private
Thread
mPushThread
;
private
byte
[]
mPpsSps
;
// private static AudioStream mAudioStream;
private
int
mChannelId
=
1
;
private
int
mChannelState
=
0
;
private
int
mFrameRate
=
25
;
private
int
mBitRate
;
private
Context
mApplicationContext
;
private
boolean
codecAvailable
=
false
;
private
byte
[]
mVps
=
new
byte
[
255
];
private
byte
[]
mSps
=
new
byte
[
255
];
private
byte
[]
mPps
=
new
byte
[
128
];
private
byte
[]
mMei
=
new
byte
[
128
];
private
byte
[]
mH264Buffer
;
private
long
timeStamp
=
System
.
currentTimeMillis
();
private
boolean
mIsRunning
=
false
;
private
boolean
mStartingService
=
false
;
@Nullable
@Override
public
IBinder
onBind
(
Intent
intent
)
{
return
null
;
}
@Override
public
void
onCreate
()
{
super
.
onCreate
();
mMpmngr
=
(
MediaProjectionManager
)
getApplicationContext
().
getSystemService
(
MEDIA_PROJECTION_SERVICE
);
// mAudioStream = new AudioStream(mEasyIPCamera);
mApplicationContext
=
getApplicationContext
();
codecAvailable
=
false
;
createEnvironment
();
}
private
void
createEnvironment
()
{
mVideoPath
=
Environment
.
getExternalStorageDirectory
().
getPath
()
+
"/"
;
wm
=
(
WindowManager
)
getSystemService
(
Context
.
WINDOW_SERVICE
);
windowWidth
=
720
;
//wm.getDefaultDisplay().getWidth();
windowHeight
=
1280
;
//wm.getDefaultDisplay().getHeight();
DisplayMetrics
displayMetrics
=
new
DisplayMetrics
();
wm
.
getDefaultDisplay
().
getMetrics
(
displayMetrics
);
screenDensity
=
displayMetrics
.
densityDpi
;
// while (windowWidth > 1080){
// windowWidth /= 2;
// windowHeight /=2;
// }
Log
.
d
(
TAG
,
String
.
format
(
"kim createEnvironment Size=%dx%d"
,
windowWidth
,
windowHeight
));
EncoderDebugger
debugger
=
EncoderDebugger
.
debug
(
mApplicationContext
,
windowWidth
,
windowHeight
);
mSps
=
Base64
.
decode
(
debugger
.
getB64SPS
(),
Base64
.
NO_WRAP
);
mPps
=
Base64
.
decode
(
debugger
.
getB64PPS
(),
Base64
.
NO_WRAP
);
mH264Buffer
=
new
byte
[(
int
)
(
windowWidth
*
windowHeight
*
1.5
)];
}
/**
* 初始化编码器
*/
private
void
initMediaCodec
()
{
mFrameRate
=
25
;
mBitRate
=
1200000
;
EncoderDebugger
debugger
=
EncoderDebugger
.
debug
(
mApplicationContext
,
windowWidth
,
windowHeight
);
mSps
=
Base64
.
decode
(
debugger
.
getB64SPS
(),
Base64
.
NO_WRAP
);
mPps
=
Base64
.
decode
(
debugger
.
getB64PPS
(),
Base64
.
NO_WRAP
);
}
@TargetApi
(
Build
.
VERSION_CODES
.
JELLY_BEAN_MR2
)
private
void
startMediaCodec
()
{
MediaFormat
mediaFormat
=
MediaFormat
.
createVideoFormat
(
"video/avc"
,
windowWidth
,
windowHeight
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_BIT_RATE
,
mBitRate
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_COLOR_FORMAT
,
MediaCodecInfo
.
CodecCapabilities
.
COLOR_FormatSurface
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_I_FRAME_INTERVAL
,
2
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_FRAME_RATE
,
mFrameRate
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_CHANNEL_COUNT
,
1
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_CAPTURE_RATE
,
mFrameRate
);
mediaFormat
.
setInteger
(
MediaFormat
.
KEY_REPEAT_PREVIOUS_FRAME_AFTER
,
1000000
/
mFrameRate
);
try
{
mMediaCodec
=
MediaCodec
.
createEncoderByType
(
"video/avc"
);
}
catch
(
IOException
e
)
{
e
.
printStackTrace
();
}
mMediaCodec
.
configure
(
mediaFormat
,
null
,
null
,
MediaCodec
.
CONFIGURE_FLAG_ENCODE
);
mSurface
=
mMediaCodec
.
createInputSurface
();
codecAvailable
=
true
;
mMediaCodec
.
start
();
startPush
();
}
/**
* 停止编码并释放编码资源占用
*/
private
void
stopMediaCodec
()
{
if
(
mMediaCodec
!=
null
)
{
codecAvailable
=
false
;
// mMediaCodec.stop();
// mMediaCodec.release();
// mMediaCodec = null;
}
stopPush
();
}
private
void
startPush
()
{
if
(
mPushThread
!=
null
)
return
;
mPushThread
=
new
Thread
(){
@TargetApi
(
Build
.
VERSION_CODES
.
LOLLIPOP
)
@Override
public
void
run
()
{
Process
.
setThreadPriority
(
Process
.
THREAD_PRIORITY_DEFAULT
);
// mAudioStream.startRecord();
while
(
mPushThread
!=
null
&&
codecAvailable
)
{
try
{
int
index
=
mMediaCodec
.
dequeueOutputBuffer
(
mBufferInfo
,
10000
);
if
((
EasyIPCamera
.
ChannelState
.
EASY_IPCAMERA_STATE_REQUEST_MEDIA_INFO
!=
mChannelState
)
&&
(
EasyIPCamera
.
ChannelState
.
EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM
!=
mChannelState
))
{
Log
.
e
(
TAG
,
"RecordService startPush state error! mChannelState="
+
mChannelState
);
continue
;
}
if
(
index
==
MediaCodec
.
INFO_TRY_AGAIN_LATER
)
{
//请求超时
try
{
// wait 10ms
Thread
.
sleep
(
10
);
}
catch
(
InterruptedException
e
)
{
}
}
else
if
(
index
>=
0
)
{
//有效输出
ByteBuffer
outputBuffer
=
mMediaCodec
.
getOutputBuffer
(
index
);
//记录pps和sps
int
type
=
outputBuffer
.
get
(
4
)
&
0x07
;
if
(
type
==
7
||
type
==
8
)
{
byte
[]
outData
=
new
byte
[
mBufferInfo
.
size
];
outputBuffer
.
get
(
outData
);
mPpsSps
=
outData
;
}
else
if
(
type
==
5
)
{
//在关键帧前面加上pps和sps数据
//在关键帧前面加上pps和sps数据
System
.
arraycopy
(
mPpsSps
,
0
,
mH264Buffer
,
0
,
mPpsSps
.
length
);
outputBuffer
.
get
(
mH264Buffer
,
mPpsSps
.
length
,
mBufferInfo
.
size
);
mEasyIPCamera
.
pushFrame
(
mChannelId
,
EasyIPCamera
.
FrameFlag
.
EASY_SDK_VIDEO_FRAME_FLAG
,
System
.
currentTimeMillis
(),
mH264Buffer
,
0
,
mPpsSps
.
length
+
mBufferInfo
.
size
);
}
else
{
outputBuffer
.
get
(
mH264Buffer
,
0
,
mBufferInfo
.
size
);
if
(
System
.
currentTimeMillis
()
-
timeStamp
>=
3000
)
{
timeStamp
=
System
.
currentTimeMillis
();
if
(
Build
.
VERSION
.
SDK_INT
>=
23
)
{
Bundle
params
=
new
Bundle
();
params
.
putInt
(
MediaCodec
.
PARAMETER_KEY_REQUEST_SYNC_FRAME
,
0
);
mMediaCodec
.
setParameters
(
params
);
}
}
mEasyIPCamera
.
pushFrame
(
mChannelId
,
EasyIPCamera
.
FrameFlag
.
EASY_SDK_VIDEO_FRAME_FLAG
,
System
.
currentTimeMillis
(),
mH264Buffer
,
0
,
mPpsSps
.
length
+
mBufferInfo
.
size
);
}
mMediaCodec
.
releaseOutputBuffer
(
index
,
false
);
}
}
catch
(
Exception
e
)
{
e
.
printStackTrace
();
break
;
}
}
if
(!
codecAvailable
){
mMediaCodec
.
stop
();
mMediaCodec
.
release
();
mMediaCodec
=
null
;
}
}
};
mPushThread
.
start
();
startVirtualDisplay
();
}
@TargetApi
(
Build
.
VERSION_CODES
.
LOLLIPOP
)
private
void
stopPush
(){
Thread
t
=
mPushThread
;
if
(
t
!=
null
){
mPushThread
=
null
;
try
{
t
.
join
();
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
// mAudioStream.stop();
if
(
mMediaCodec
!=
null
)
{
mMediaCodec
.
stop
();
mMediaCodec
.
release
();
mMediaCodec
=
null
;
}
}
@TargetApi
(
Build
.
VERSION_CODES
.
LOLLIPOP
)
private
void
startVirtualDisplay
()
{
if
(
mMpj
==
null
)
{
mMpj
=
mMpmngr
.
getMediaProjection
(
StreameActivity
.
mResultCode
,
StreameActivity
.
mResultIntent
);
StreameActivity
.
mResultCode
=
0
;
StreameActivity
.
mResultIntent
=
null
;
}
mVirtualDisplay
=
mMpj
.
createVirtualDisplay
(
"record_screen"
,
windowWidth
,
windowHeight
,
screenDensity
,
DisplayManager
.
VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR
|
DisplayManager
.
VIRTUAL_DISPLAY_FLAG_PUBLIC
|
DisplayManager
.
VIRTUAL_DISPLAY_FLAG_PRESENTATION
,
mSurface
,
null
,
null
);
}
@TargetApi
(
Build
.
VERSION_CODES
.
KITKAT
)
private
void
release
()
{
Log
.
i
(
TAG
,
" release() "
);
if
(
mSurface
!=
null
){
mSurface
.
release
();
}
if
(
mVirtualDisplay
!=
null
)
{
mVirtualDisplay
.
release
();
mVirtualDisplay
=
null
;
}
}
@Override
public
int
onStartCommand
(
Intent
intent
,
int
flags
,
int
startId
)
{
mIsRunning
=
true
;
mStartingService
=
true
;
String
strPort
=
EasyApplication
.
getEasyApplication
().
getPort
();
final
String
strId
=
EasyApplication
.
getEasyApplication
().
getId
();
if
(
strPort
==
null
||
strPort
.
isEmpty
()
||
strId
==
null
||
strId
.
isEmpty
())
{
mStartingService
=
false
;
return
START_STICKY
;
}
final
int
iport
=
Integer
.
parseInt
(
strPort
);
if
(
mEasyIPCamera
==
null
)
{
mStartingService
=
false
;
return
START_STICKY
;
}
mChannelId
=
mEasyIPCamera
.
registerCallback
(
this
);
// mAudioStream.setChannelId(mChannelId);
// mAudioStream.startRecord();
new
Thread
(
new
Runnable
()
{
@Override
public
void
run
()
{
int
result
=
-
1
;
while
(
mIsRunning
&&
result
<
0
)
{
result
=
mEasyIPCamera
.
startup
(
iport
,
EasyIPCamera
.
AuthType
.
AUTHENTICATION_TYPE_BASIC
,
""
,
""
,
""
,
0
,
mChannelId
,
strId
.
getBytes
());
if
(
result
<
0
){
try
{
Thread
.
sleep
(
100
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
Log
.
d
(
TAG
,
"kim startup result="
+
result
);
}
initMediaCodec
();
mStartingService
=
false
;
}
}).
start
();
int
ret
=
super
.
onStartCommand
(
intent
,
flags
,
startId
);
return
ret
;
}
@TargetApi
(
Build
.
VERSION_CODES
.
LOLLIPOP
)
@Override
public
void
onDestroy
()
{
new
Thread
(
new
Runnable
()
{
@Override
public
void
run
()
{
mIsRunning
=
false
;
while
(
mStartingService
){
try
{
Thread
.
sleep
(
100
);
}
catch
(
InterruptedException
e
)
{
e
.
printStackTrace
();
}
}
stopPush
();
setChannelState
(
0
);
mEasyIPCamera
.
resetChannel
(
mChannelId
);
int
result
=
mEasyIPCamera
.
shutdown
();
Log
.
d
(
TAG
,
"kim shutdown result="
+
result
);
mEasyIPCamera
.
unrigisterCallback
(
RecordService
.
this
);
mEasyIPCamera
=
null
;
release
();
if
(
mMpj
!=
null
)
{
mMpj
.
stop
();
}
//super.onDestroy();
}
}).
start
();
}
private
void
setChannelState
(
int
state
){
if
(
state
<=
2
)
{
mChannelState
=
state
;
// mAudioStream.setChannelState(state);
}
}
@Override
public
void
onIPCameraCallBack
(
int
channelId
,
int
channelState
,
byte
[]
mediaInfo
,
int
userPtr
)
{
// Log.d(TAG, "kim onIPCameraCallBack, channelId="+channelId+", mChannelId="+mChannelId+", channelState="+channelState);
if
(
channelId
!=
mChannelId
)
return
;
setChannelState
(
channelState
);
switch
(
channelState
){
case
EasyIPCamera
.
ChannelState
.
EASY_IPCAMERA_STATE_ERROR
:
Log
.
d
(
TAG
,
"Screen Record EASY_IPCAMERA_STATE_ERROR"
);
Util
.
showDbgMsg
(
StatusInfoView
.
DbgLevel
.
DBG_LEVEL_WARN
,
"Screen Record EASY_IPCAMERA_STATE_ERROR"
);
break
;
case
EasyIPCamera
.
ChannelState
.
EASY_IPCAMERA_STATE_REQUEST_MEDIA_INFO
:
Util
.
showDbgMsg
(
StatusInfoView
.
DbgLevel
.
DBG_LEVEL_INFO
,
"Screen Record EASY_IPCAMERA_STATE_REQUEST_MEDIA_INFO"
);
ByteBuffer
buffer
=
ByteBuffer
.
wrap
(
mediaInfo
);
buffer
.
order
(
ByteOrder
.
LITTLE_ENDIAN
);
buffer
.
putInt
(
EasyIPCamera
.
VideoCodec
.
EASY_SDK_VIDEO_CODEC_H264
);
buffer
.
putInt
(
mFrameRate
);
// buffer.putInt(mAudioStream.getAudioEncCodec());
// buffer.putInt(mAudioStream.getSamplingRate());
// buffer.putInt(mAudioStream.getChannelNum());
// buffer.putInt(mAudioStream.getBitsPerSample());
buffer
.
putInt
(
0
);
buffer
.
putInt
(
0
);
buffer
.
putInt
(
0
);
buffer
.
putInt
(
0
);
buffer
.
putInt
(
0
);
//vps length
buffer
.
putInt
(
mSps
.
length
);
buffer
.
putInt
(
mPps
.
length
);
buffer
.
putInt
(
0
);
buffer
.
put
(
mVps
);
buffer
.
put
(
mSps
,
0
,
mSps
.
length
);
if
(
mSps
.
length
<
255
)
{
buffer
.
put
(
mVps
,
0
,
255
-
mSps
.
length
);
}
buffer
.
put
(
mPps
,
0
,
mPps
.
length
);
if
(
mPps
.
length
<
128
)
{
buffer
.
put
(
mVps
,
0
,
128
-
mPps
.
length
);
}
buffer
.
put
(
mMei
);
break
;
case
EasyIPCamera
.
ChannelState
.
EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM
:
Util
.
showDbgMsg
(
StatusInfoView
.
DbgLevel
.
DBG_LEVEL_INFO
,
"Screen Record EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM"
);
startMediaCodec
();
//mAudioStream.startPush();
break
;
case
EasyIPCamera
.
ChannelState
.
EASY_IPCAMERA_STATE_REQUEST_STOP_STREAM
:
Util
.
showDbgMsg
(
StatusInfoView
.
DbgLevel
.
DBG_LEVEL_INFO
,
"Screen Record EASY_IPCAMERA_STATE_REQUEST_STOP_STREAM"
);
stopMediaCodec
();
//mAudioStream.stopPush();
break
;
default
:
break
;
}
}
}
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/SettingActivity.java
浏览文件 @
4d59186e
/*
Copyright (c) 2012-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2012-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
...
...
@@ -8,15 +8,19 @@
package
org.easydarwin.easyipcamera.activity
;
import
android.os.Bundle
;
import
android.preference.PreferenceManager
;
import
android.support.v7.app.AppCompatActivity
;
import
android.text.TextUtils
;
import
android.view.View
;
import
android.widget.Button
;
import
android.widget.CheckBox
;
import
android.widget.CompoundButton
;
import
android.widget.EditText
;
import
android.widget.TextView
;
import
android.widget.Toast
;
import
org.easydarwin.easyipcamera.R
;
import
org.easydarwin.easyipcamera.camera.MediaStream
;
import
org.easydarwin.easyipcamera.config.Config
;
import
org.easydarwin.easyipcamera.util.Util
;
...
...
@@ -38,6 +42,15 @@ public class SettingActivity extends AppCompatActivity {
txtPort
.
setText
(
port
);
txtId
.
setText
(
id
);
CheckBox
x264enc
=
(
CheckBox
)
findViewById
(
R
.
id
.
use_x264_encode
);
x264enc
.
setChecked
(
PreferenceManager
.
getDefaultSharedPreferences
(
this
).
getBoolean
(
"key-sw-codec"
,
MediaStream
.
useSWCodec
()));
x264enc
.
setOnCheckedChangeListener
(
new
CompoundButton
.
OnCheckedChangeListener
()
{
@Override
public
void
onCheckedChanged
(
CompoundButton
buttonView
,
boolean
isChecked
)
{
PreferenceManager
.
getDefaultSharedPreferences
(
SettingActivity
.
this
).
edit
().
putBoolean
(
"key-sw-codec"
,
isChecked
).
apply
();
}
});
Button
btnSave
=
(
Button
)
findViewById
(
R
.
id
.
btn_save
);
btnSave
.
setOnClickListener
(
new
View
.
OnClickListener
()
{
@Override
...
...
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/SplashActivity.java
浏览文件 @
4d59186e
/*
Copyright (c) 2012-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2012-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
...
...
Android/app/src/main/java/org/easydarwin/easyipcamera/activity/StreameActivity.java
浏览文件 @
4d59186e
/*
Copyright (c) 2012-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2012-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
*/
package
org.easydarwin.easyipcamera.activity
;
import
android.content.DialogInterface
;
import
android.content.Intent
;
import
android.media.projection.MediaProjectionManager
;
import
android.os.Build
;
import
android.os.Bundle
;
import
android.
os.Handl
er
;
import
android.
os.Message
;
import
android.
preference.PreferenceManag
er
;
import
android.
support.v7.app.AlertDialog
;
import
android.support.v7.app.AppCompatActivity
;
import
android.util.Log
;
import
android.view.Surface
;
...
...
@@ -25,6 +28,7 @@ import android.widget.Spinner;
import
android.widget.TextView
;
import
org.easydarwin.easyipcamera.R
;
import
org.easydarwin.easyipcamera.camera.EasyIPCamera
;
import
org.easydarwin.easyipcamera.camera.MediaStream
;
import
org.easydarwin.easyipcamera.updatemgr.UpdateMgr
;
import
org.easydarwin.easyipcamera.util.Util
;
...
...
@@ -37,18 +41,21 @@ import java.util.List;
public
class
StreameActivity
extends
AppCompatActivity
implements
SurfaceHolder
.
Callback
,
View
.
OnClickListener
{
static
final
String
TAG
=
"StreameActivity"
;
public
static
final
int
REQUEST_MEDIA_PROJECTION
=
1002
;
//默认分辨率
int
width
=
640
,
height
=
480
;
Button
btnSwitch
;
Button
btnSetting
;
Button
btnPushScreen
;
TextView
txtStreamAddress
;
Button
btnSwitchCemera
;
Spinner
spnResolution
;
List
<
String
>
listResolution
;
MediaStream
mMediaStream
;
private
StatusInfoView
mDbgInfoPrint
;
private
boolean
mIsStarted
=
false
;
static
Intent
mResultIntent
;
static
int
mResultCode
;
@Override
protected
void
onCreate
(
Bundle
savedInstanceState
)
{
...
...
@@ -67,6 +74,8 @@ public class StreameActivity extends AppCompatActivity implements SurfaceHolder.
btnSetting
.
setOnClickListener
(
this
);
btnSwitchCemera
=
(
Button
)
findViewById
(
R
.
id
.
btn_switchCamera
);
btnSwitchCemera
.
setOnClickListener
(
this
);
btnPushScreen
=
(
Button
)
findViewById
(
R
.
id
.
push_screen
);
btnPushScreen
.
setOnClickListener
(
this
);
txtStreamAddress
=
(
TextView
)
findViewById
(
R
.
id
.
txt_stream_address
);
SurfaceView
surfaceView
=
(
SurfaceView
)
findViewById
(
R
.
id
.
sv_surfaceview
);
surfaceView
.
getHolder
().
addCallback
(
this
);
...
...
@@ -89,7 +98,11 @@ public class StreameActivity extends AppCompatActivity implements SurfaceHolder.
mMediaStream
.
setDgree
(
getDgree
());
initSpninner
();
mIsStarted
=
false
;
if
(
RecordService
.
mEasyIPCamera
!=
null
){
btnPushScreen
.
setText
(
"停止推送屏幕"
);
TextView
viewById
=
(
TextView
)
findViewById
(
R
.
id
.
txt_stream_address
);
viewById
.
setText
(
getRTSPAddr
());
}
UpdateMgr
update
=
new
UpdateMgr
(
this
);
update
.
checkUpdate
();
...
...
@@ -111,7 +124,7 @@ public class StreameActivity extends AppCompatActivity implements SurfaceHolder.
adapter
.
setDropDownViewResource
(
android
.
R
.
layout
.
simple_spinner_dropdown_item
);
spnResolution
.
setAdapter
(
adapter
);
int
position
=
listResolution
.
indexOf
(
String
.
format
(
"%dx%d"
,
width
,
height
));
spnResolution
.
setSelection
(
position
);
spnResolution
.
setSelection
(
position
,
false
);
spnResolution
.
setOnItemSelectedListener
(
new
AdapterView
.
OnItemSelectedListener
()
{
@Override
public
void
onItemSelected
(
AdapterView
<?>
parent
,
View
view
,
int
position
,
long
id
)
{
...
...
@@ -144,8 +157,10 @@ public class StreameActivity extends AppCompatActivity implements SurfaceHolder.
@Override
public
void
surfaceDestroyed
(
SurfaceHolder
holder
)
{
mMediaStream
.
stopPreview
();
mMediaStream
.
stopStream
();
mMediaStream
.
destroyCamera
();
if
(
mMediaStream
.
isOpen
()){
mMediaStream
.
stopChannel
();
}
}
...
...
@@ -169,27 +184,40 @@ public class StreameActivity extends AppCompatActivity implements SurfaceHolder.
return
degrees
;
}
private
String
getRTSPAddr
(){
String
ip
=
Util
.
getLocalIpAddress
();
String
port
=
EasyApplication
.
getEasyApplication
().
getPort
();
String
id
=
EasyApplication
.
getEasyApplication
().
getId
();
return
String
.
format
(
"rtsp://%s:%s/%s"
,
ip
,
port
,
id
);
}
@Override
public
void
onClick
(
View
v
)
{
switch
(
v
.
getId
())
{
case
R
.
id
.
btn_switch
:
StatusInfoView
.
getInstence
().
clearMsg
();
if
(!
mIsStarted
)
{
if
(!
mMediaStream
.
isOpen
())
{
btnSetting
.
setEnabled
(
false
);
btnPushScreen
.
setEnabled
(
false
);
btnSwitchCemera
.
setEnabled
(
false
);
String
ip
=
Util
.
getLocalIpAddress
();
String
port
=
EasyApplication
.
getEasyApplication
().
getPort
();
String
id
=
EasyApplication
.
getEasyApplication
().
getId
();
mMediaStream
.
start
Stream
(
ip
,
port
,
id
);
mMediaStream
.
start
Channel
(
ip
,
port
,
id
);
btnSwitch
.
setText
(
"停止"
);
txtStreamAddress
.
setVisibility
(
View
.
VISIBLE
);
StatusInfoView
.
getInstence
().
setVisibility
(
View
.
VISIBLE
);
txtStreamAddress
.
setText
(
String
.
format
(
"rtsp://%s:%s/%s"
,
ip
,
port
,
id
));
mIsStarted
=
true
;
txtStreamAddress
.
setText
(
String
.
format
(
getRTSPAddr
()));
}
else
{
txtStreamAddress
.
setVisibility
(
View
.
INVISIBLE
);
StatusInfoView
.
getInstence
().
setVisibility
(
View
.
INVISIBLE
);
mMediaStream
.
stopStream
();
btnSwitch
.
setText
(
"开始"
);
mIsStarted
=
false
;
mMediaStream
.
stopChannel
();
btnSwitch
.
setText
(
"推送摄像头"
);
btnSetting
.
setEnabled
(
true
);
btnPushScreen
.
setEnabled
(
true
);
btnSwitchCemera
.
setEnabled
(
true
);
}
break
;
case
R
.
id
.
btn_setting
:
...
...
@@ -204,14 +232,130 @@ public class StreameActivity extends AppCompatActivity implements SurfaceHolder.
case
R
.
id
.
btn_switchCamera
:
{
mMediaStream
.
setDgree
(
getDgree
());
mMediaStream
.
switchCamera
();
break
;
}
case
R
.
id
.
push_screen
:
if
(!
mMediaStream
.
isOpen
())
{
spnResolution
.
setEnabled
(
true
);
}
//sendMessage("");
boolean
SWcodec
=
PreferenceManager
.
getDefaultSharedPreferences
(
EasyApplication
.
getEasyApplication
()).
getBoolean
(
"key-sw-codec"
,
false
);
if
(
SWcodec
){
new
AlertDialog
.
Builder
(
this
).
setMessage
(
"推送屏幕暂时只支持硬编码,请使用硬件编码。"
).
setTitle
(
"抱歉"
).
show
();
}
else
{
onPushScreen
();
}
break
;
default
:
break
;
}
}
private
void
startScreenPushIntent
()
{
if
(
StreameActivity
.
mResultIntent
!=
null
&&
StreameActivity
.
mResultCode
!=
0
)
{
RecordService
.
mEasyIPCamera
=
new
EasyIPCamera
();
RecordService
.
mEasyIPCamera
.
active
(
getApplicationContext
());
Intent
intent
=
new
Intent
(
getApplicationContext
(),
RecordService
.
class
);
startService
(
intent
);
txtStreamAddress
.
setVisibility
(
View
.
VISIBLE
);
txtStreamAddress
.
setText
(
String
.
format
(
getRTSPAddr
()));
btnPushScreen
.
setText
(
"停止推送屏幕"
);
}
else
{
if
(
Build
.
VERSION
.
SDK_INT
>=
Build
.
VERSION_CODES
.
LOLLIPOP
)
{
MediaProjectionManager
mMpMngr
=
(
MediaProjectionManager
)
getApplicationContext
().
getSystemService
(
MEDIA_PROJECTION_SERVICE
);
startActivityForResult
(
mMpMngr
.
createScreenCaptureIntent
(),
StreameActivity
.
REQUEST_MEDIA_PROJECTION
);
}
}
}
public
void
onPushScreen
()
{
if
(
Build
.
VERSION
.
SDK_INT
<
Build
.
VERSION_CODES
.
LOLLIPOP
){
new
AlertDialog
.
Builder
(
this
).
setMessage
(
"推送屏幕需要安卓5.0以上,您当前系统版本过低,不支持该功能。"
).
setTitle
(
"抱歉"
).
show
();
return
;
}
if
(!
PreferenceManager
.
getDefaultSharedPreferences
(
this
).
getBoolean
(
"alert_screen_background_pushing"
,
false
)){
new
AlertDialog
.
Builder
(
this
).
setTitle
(
"提醒"
).
setMessage
(
"屏幕直播将要开始,直播过程中您可以切换到其它屏幕。不过记得直播结束后,再进来停止直播哦!"
).
setPositiveButton
(
android
.
R
.
string
.
ok
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialogInterface
,
int
i
)
{
PreferenceManager
.
getDefaultSharedPreferences
(
StreameActivity
.
this
).
edit
().
putBoolean
(
"alert_screen_background_pushing"
,
true
).
apply
();
onPushScreen
();
}
}).
show
();
return
;
}
if
(
RecordService
.
mEasyIPCamera
!=
null
)
{
Intent
intent
=
new
Intent
(
getApplicationContext
(),
RecordService
.
class
);
stopService
(
intent
);
TextView
viewById
=
(
TextView
)
findViewById
(
R
.
id
.
txt_stream_address
);
viewById
.
setText
(
null
);
btnPushScreen
.
setText
(
"推送屏幕"
);
btnSwitch
.
setEnabled
(
true
);
btnSwitchCemera
.
setEnabled
(
true
);
btnSetting
.
setEnabled
(
true
);
}
else
{
btnSwitch
.
setEnabled
(
false
);
btnSwitchCemera
.
setEnabled
(
false
);
btnSetting
.
setEnabled
(
false
);
startScreenPushIntent
();
}
}
@Override
protected
void
onActivityResult
(
int
requestCode
,
int
resultCode
,
Intent
data
)
{
super
.
onActivityResult
(
requestCode
,
resultCode
,
data
);
if
(
requestCode
==
REQUEST_MEDIA_PROJECTION
)
{
if
(
resultCode
==
RESULT_OK
)
{
Log
.
e
(
TAG
,
"get capture permission success!"
);
mResultCode
=
resultCode
;
mResultIntent
=
data
;
startScreenPushIntent
();
}
break
;
}
}
@Override
protected
void
onDestroy
()
{
mMediaStream
.
destroyChannel
();
StatusInfoView
.
getInstence
().
uninit
();
super
.
onDestroy
();
mMediaStream
.
destroyStream
();
}
@Override
protected
void
onStop
()
{
StatusInfoView
.
getInstence
().
uninit
();
super
.
onStop
();
}
/**
* Take care of popping the fragment back stack or finishing the activity
* as appropriate.
*/
@Override
public
void
onBackPressed
()
{
boolean
isStreaming
=
mMediaStream
!=
null
&&
mMediaStream
.
isOpen
();
if
(
isStreaming
&&
PreferenceManager
.
getDefaultSharedPreferences
(
this
).
getBoolean
(
"key_enable_background_camera"
,
true
)){
if
(!
PreferenceManager
.
getDefaultSharedPreferences
(
this
).
getBoolean
(
"background_camera_alert"
,
false
)){
new
AlertDialog
.
Builder
(
this
).
setTitle
(
"提醒"
).
setMessage
(
"您设置了使能摄像头后台采集,因此摄像头将会继续在后台采集并上传视频。记得直播结束后,再回来这里关闭直播。"
).
setPositiveButton
(
android
.
R
.
string
.
ok
,
new
DialogInterface
.
OnClickListener
()
{
@Override
public
void
onClick
(
DialogInterface
dialogInterface
,
int
i
)
{
PreferenceManager
.
getDefaultSharedPreferences
(
StreameActivity
.
this
).
edit
().
putBoolean
(
"background_camera_alert"
,
true
).
apply
();
StreameActivity
.
super
.
onBackPressed
();
}
}).
show
();
return
;
}
super
.
onBackPressed
();
}
else
{
super
.
onBackPressed
();
}
}
}
Android/app/src/main/java/org/easydarwin/easyipcamera/camera/AudioStream.java
浏览文件 @
4d59186e
/*
Copyright (c) 2012-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2012-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
...
...
@@ -40,7 +40,8 @@ public class AudioStream {
private
Thread
encodeThread
=
null
;
String
TAG
=
"AudioStream"
;
//final String path = Environment.getExternalStorageDirectory() + "/123450001.aac";
boolean
stoped
=
false
;
private
boolean
stoped
=
false
;
private
boolean
mPushAudio
=
false
;
private
int
mChannelState
=
0
;
protected
MediaCodec
.
BufferInfo
mBufferInfo
=
new
MediaCodec
.
BufferInfo
();
...
...
@@ -81,6 +82,7 @@ public class AudioStream {
private
void
init
()
{
try
{
stoped
=
false
;
mPushAudio
=
false
;
mAudioEncCodec
=
EasyIPCamera
.
AudioCodec
.
EASY_SDK_AUDIO_CODEC_AAC
;
mBitsPerSample
=
16
;
//AudioFormat.ENCODING_PCM_16BIT;
mChannelNum
=
1
;
...
...
@@ -154,20 +156,20 @@ public class AudioStream {
}
}
}
int
size
=
mBufferInfo
.
size
+
7
;
byte
[]
buffer
=
new
byte
[
size
];
mBuffer
.
get
(
buffer
);
Log
.
d
(
TAG
,
"kim mChannelState="
+
mChannelState
+
", mChannelId="
+
mChannelId
+
", length="
+
buffer
.
length
);
if
(
mChannelState
==
EasyIPCamera
.
ChannelState
.
EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM
)
{
mEasyIPCamera
.
pushFrame
(
mChannelId
,
EasyIPCamera
.
FrameFlag
.
EASY_SDK_AUDIO_FRAME_FLAG
,
System
.
currentTimeMillis
(),
buffer
);
int
size
=
mBufferInfo
.
size
+
7
;
//Log.d(TAG, "kim mChannelState="+mChannelState+", mChannelId="+mChannelId+", length="+buffer.length);
if
(
mPushAudio
&&
mChannelState
==
EasyIPCamera
.
ChannelState
.
EASY_IPCAMERA_STATE_REQUEST_PLAY_STREAM
)
{
// byte[] buffer = new byte[size];
// mBuffer.get(buffer, 0, size);
mEasyIPCamera
.
pushFrame
(
mChannelId
,
EasyIPCamera
.
FrameFlag
.
EASY_SDK_AUDIO_FRAME_FLAG
,
System
.
currentTimeMillis
(),
mBuffer
.
array
(),
0
,
size
);
}
if
(
mBuffer
.
position
()
>=
size
)
{
// read complete
mMediaCodec
.
releaseOutputBuffer
(
mIndex
,
false
);
mBuffer
=
null
;
}
}
catch
(
Runtime
Exception
e
)
{
}
catch
(
Exception
e
)
{
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
);
e
.
printStackTrace
(
pw
);
...
...
@@ -210,7 +212,7 @@ public class AudioStream {
}
}
}
}
catch
(
Runtime
Exception
e
)
{
}
catch
(
Exception
e
)
{
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
);
e
.
printStackTrace
(
pw
);
...
...
@@ -265,6 +267,14 @@ public class AudioStream {
stoped
=
true
;
}
public
void
startPush
(){
mPushAudio
=
true
;
}
public
void
stopPush
(){
mPushAudio
=
false
;
}
public
int
getAudioEncCodec
(){
return
mAudioEncCodec
;
}
...
...
Android/app/src/main/java/org/easydarwin/easyipcamera/camera/EasyIPCamera.java
浏览文件 @
4d59186e
/*
Copyright (c) 2012-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2012-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
...
...
@@ -7,6 +7,7 @@
package
org.easydarwin.easyipcamera.camera
;
import
android.content.Context
;
import
android.util.Log
;
import
android.util.SparseArray
;
...
...
@@ -58,14 +59,14 @@ public class EasyIPCamera {
public
static
final
int
EASY_SDK_AUDIO_CODEC_G726
=
0x1100B
;
/* G726 */
}
int
registerCallback
(
IPCameraCallBack
cb
)
{
public
int
registerCallback
(
IPCameraCallBack
cb
)
{
synchronized
(
sCallbacks
)
{
sCallbacks
.
put
(++
sKey
,
cb
);
return
sKey
;
}
}
void
unrigisterCallback
(
IPCameraCallBack
cb
)
{
public
void
unrigisterCallback
(
IPCameraCallBack
cb
)
{
synchronized
(
sCallbacks
)
{
int
idx
=
sCallbacks
.
indexOfValue
(
cb
);
if
(
idx
!=
-
1
)
{
...
...
@@ -89,6 +90,8 @@ public class EasyIPCamera {
return
;
}
public
native
int
active
(
String
key
,
Context
context
);
/* 启动 Rtsp Server */
/*设置监听端口, 回调函数及自定义数据 */
public
native
int
startup
(
int
listenport
,
int
authType
,
String
realm
,
String
username
,
String
password
,
int
userptr
,
int
channelid
,
byte
[]
channelinfo
);
...
...
@@ -97,11 +100,24 @@ public class EasyIPCamera {
public
native
int
shutdown
();
/* frame: 具体发送的帧数据 */
public
native
int
pushFrame
(
int
channelId
,
int
avFrameFlag
,
long
timestamp
,
byte
[]
pBuffer
);
public
native
int
pushFrame
(
int
channelId
,
int
avFrameFlag
,
long
timestamp
,
byte
[]
pBuffer
,
int
offset
,
int
length
);
public
native
int
resetChannel
(
int
channelId
);
public
interface
IPCameraCallBack
{
void
onIPCameraCallBack
(
int
channelId
,
int
channelState
,
byte
[]
mediaInfo
,
int
userPtr
);
}
public
int
active
(
Context
context
){
String
key
=
"6D72754B7A4A36526D343041344B68597031636670655276636D63755A57467A65575268636E64706269356C59584E356158426A5957316C636D4658444661672F365867523246326157346D516D466962334E68514449774D545A4659584E355247467964326C75564756686257566863336B3D"
;
int
iRet
=
active
(
key
,
context
);
if
(
iRet
!=
0
){
Log
.
e
(
TAG
,
"Key invalid! active failed!!! return : "
+
iRet
);
}
return
iRet
;
}
public
int
pushFrame
(
int
channelId
,
int
avFrameFlag
,
long
timestamp
,
byte
[]
pBuffer
){
return
pushFrame
(
channelId
,
avFrameFlag
,
timestamp
,
pBuffer
,
0
,
pBuffer
.
length
);
}
}
\ No newline at end of file
Android/app/src/main/java/org/easydarwin/easyipcamera/camera/MediaStream.java
浏览文件 @
4d59186e
此差异已折叠。
点击以展开。
Android/app/src/main/java/org/easydarwin/easyipcamera/config/Config.java
浏览文件 @
4d59186e
/*
Copyright (c) 2012-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2012-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
...
...
Android/app/src/main/java/org/easydarwin/easyipcamera/hw/CodecManager.java
浏览文件 @
4d59186e
/*
Copyright (c) 2012-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2012-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
...
...
Android/app/src/main/java/org/easydarwin/easyipcamera/sw/JNIUtil.java
0 → 100644
浏览文件 @
4d59186e
package
org.easydarwin.easyipcamera.sw
;
/**
*/
public
class
JNIUtil
{
static
{
System
.
loadLibrary
(
"Utils"
);
}
/**
* 都是Y:U:V = 4:1:1但 U与 V顺序相反。变换可逆
*
* @param buffer
* @param width
* @param height
*/
public
static
void
yV12ToYUV420P
(
byte
[]
buffer
,
int
width
,
int
height
)
{
callMethod
(
"YV12ToYUV420P"
,
null
,
buffer
,
width
,
height
);
}
/**
* 都是Y:U+V = 4:2,但是这两者U、V方向相反。变换可逆
*
* @param buffer
* @param width
* @param height
*/
public
static
void
nV21To420SP
(
byte
[]
buffer
,
int
width
,
int
height
)
{
callMethod
(
"NV21To420SP"
,
null
,
buffer
,
width
,
height
);
}
/**
* 旋转1个字节为单位的矩阵
*
* @param data 要旋转的矩阵
* @param offset 偏移量
* @param width 宽度
* @param height 高度
* @param degree 旋转度数
*/
public
static
void
rotateMatrix
(
byte
[]
data
,
int
offset
,
int
width
,
int
height
,
int
degree
)
{
callMethod
(
"RotateByteMatrix"
,
null
,
data
,
offset
,
width
,
height
,
degree
);
}
/**
* 旋转2个字节为单位的矩阵
*
* @param data 要旋转的矩阵
* @param offset 偏移量
* @param width 宽度
* @param height 高度
* @param degree 旋转度数
*/
public
static
void
rotateShortMatrix
(
byte
[]
data
,
int
offset
,
int
width
,
int
height
,
int
degree
)
{
callMethod
(
"RotateShortMatrix"
,
null
,
data
,
offset
,
width
,
height
,
degree
);
}
private
static
native
void
callMethod
(
String
methodName
,
Object
[]
returnValue
,
Object
...
params
);
}
Android/app/src/main/java/org/easydarwin/easyipcamera/sw/X264Encoder.java
0 → 100644
浏览文件 @
4d59186e
package
org.easydarwin.easyipcamera.sw
;
public
class
X264Encoder
{
static
{
System
.
loadLibrary
(
"x264enc"
);
}
private
long
mHandle
;
/**
* 创建编码器
*
* @param w 要编码的视频的宽度
* @param h 要编码的视频的高度
* @param bitrate 要编码的码率
*/
public
void
create
(
int
w
,
int
h
,
int
frameRate
,
int
bitrate
)
{
long
[]
handle
=
new
long
[
1
];
create
(
w
,
h
,
frameRate
,
bitrate
,
handle
);
mHandle
=
handle
[
0
];
}
/**
* 获取头信息
*
* @param sps yv12格式的视频数据(数据长度应该为w*h*1.5)
* @param spslen 视频数据的偏移(即在yv12里的起始位)
* @param pps 编码后的数据。
* @param ppslen 编码后的视频数据的偏移(即在out里的起始位)
* @return returns negative on error, zero if success.
*/
public
int
getSpsPps
(
byte
[]
sps
,
int
[]
spslen
,
byte
[]
pps
,
int
[]
ppslen
)
{
return
getSpsPps
(
mHandle
,
sps
,
spslen
,
pps
,
ppslen
);
}
/**
* 编码
*
* @param yv12 yv12格式的视频数据(数据长度应该为w*h*1.5)
* @param offset 视频数据的偏移(即在yv12里的起始位)
* @param out 编码后的数据。
* @param outOffset 编码后的视频数据的偏移(即在out里的起始位)
* @param outLen outLen[0]为编码后的视频数据的长度
* @param keyFrame keyFrame[0]为编码后的视频帧的关键帧标识
* @return returns negative on error, zero if no NAL units returned.
*/
public
int
encode
(
byte
[]
yv12
,
int
offset
,
byte
[]
out
,
int
outOffset
,
int
[]
outLen
,
byte
[]
keyFrame
)
{
return
encode
(
mHandle
,
yv12
,
offset
,
out
,
outOffset
,
outLen
,
keyFrame
);
}
/**
* 关闭编码器
*/
public
void
close
()
{
close
(
mHandle
);
}
private
static
native
void
create
(
int
width
,
int
height
,
int
frameRate
,
int
bitRate
,
long
[]
handle
);
private
static
native
int
getSpsPps
(
long
handle
,
byte
[]
sps
,
int
[]
spslen
,
byte
[]
pps
,
int
[]
ppslen
);
private
static
native
int
encode
(
long
handle
,
byte
[]
buffer
,
int
offset
,
byte
[]
out
,
int
outOffset
,
int
[]
outLen
,
byte
[]
keyFrame
);
private
static
native
void
close
(
long
handle
);
}
Android/app/src/main/java/org/easydarwin/easyipcamera/util/Util.java
浏览文件 @
4d59186e
/*
Copyright (c) 2013-201
6
EasyDarwin.ORG. All rights reserved.
Copyright (c) 2013-201
7
EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.easydarwin.org
...
...
@@ -8,10 +8,18 @@
package
org.easydarwin.easyipcamera.util
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.SharedPreferences
;
import
android.net.wifi.WifiInfo
;
import
android.net.wifi.WifiManager
;
import
android.support.v4.content.LocalBroadcastManager
;
import
android.text.TextUtils
;
import
android.util.Log
;
import
org.easydarwin.easyipcamera.activity.EasyApplication
;
import
org.easydarwin.easyipcamera.config.Config
;
import
org.easydarwin.easyipcamera.sw.JNIUtil
;
import
org.easydarwin.easyipcamera.view.StatusInfoView
;
import
java.io.FileNotFoundException
;
import
java.io.FileOutputStream
;
...
...
@@ -152,6 +160,30 @@ public class Util {
return
dst
;
}
/**
* 旋转YUV格式数据
*
* @param src YUV数据
* @param format 0,420P;1,420SP
* @param width 宽度
* @param height 高度
* @param degree 旋转度数
*/
public
static
void
yuvRotate
(
byte
[]
src
,
int
format
,
int
width
,
int
height
,
int
degree
)
{
int
offset
=
0
;
if
(
format
==
0
)
{
JNIUtil
.
rotateMatrix
(
src
,
offset
,
width
,
height
,
degree
);
offset
+=
(
width
*
height
);
JNIUtil
.
rotateMatrix
(
src
,
offset
,
width
/
2
,
height
/
2
,
degree
);
offset
+=
width
*
height
/
4
;
JNIUtil
.
rotateMatrix
(
src
,
offset
,
width
/
2
,
height
/
2
,
degree
);
}
else
if
(
format
==
1
)
{
JNIUtil
.
rotateMatrix
(
src
,
offset
,
width
,
height
,
degree
);
offset
+=
width
*
height
;
JNIUtil
.
rotateShortMatrix
(
src
,
offset
,
width
/
2
,
height
/
2
,
degree
);
}
}
/**
* 保存数据到本地
*
...
...
@@ -211,24 +243,50 @@ public class Util {
sharedPreferences
.
edit
().
putString
(
Config
.
K_RESOLUTION
,
value
).
commit
();
}
private
static
String
intToIp
(
int
i
)
{
return
(
i
&
0xFF
)
+
"."
+
((
i
>>
8
)
&
0xFF
)
+
"."
+
((
i
>>
16
)
&
0xFF
)
+
"."
+
(
i
>>
24
&
0xFF
)
;
}
/**
* 获取IP地址
*/
public
static
String
getLocalIpAddress
()
{
String
localIP
=
""
;
try
{
for
(
Enumeration
<
NetworkInterface
>
en
=
NetworkInterface
.
getNetworkInterfaces
();
en
.
hasMoreElements
();)
{
NetworkInterface
intf
=
en
.
nextElement
();
for
(
Enumeration
<
InetAddress
>
enumIpAddr
=
intf
.
getInetAddresses
();
enumIpAddr
.
hasMoreElements
();)
{
InetAddress
inetAddress
=
enumIpAddr
.
nextElement
();
if
(!
inetAddress
.
isLoopbackAddress
())
{
localIP
=
inetAddress
.
getHostAddress
().
toString
();
//获取wifi服务
WifiManager
wifiManager
=
(
WifiManager
)
EasyApplication
.
getEasyApplication
().
getSystemService
(
Context
.
WIFI_SERVICE
);
//判断wifi是否开启
if
(
wifiManager
.
isWifiEnabled
())
{
WifiInfo
wifiInfo
=
wifiManager
.
getConnectionInfo
();
int
ipAddress
=
wifiInfo
.
getIpAddress
();
String
ip
=
intToIp
(
ipAddress
);
return
ip
;
}
else
{
try
{
for
(
Enumeration
<
NetworkInterface
>
en
=
NetworkInterface
.
getNetworkInterfaces
();
en
.
hasMoreElements
();)
{
NetworkInterface
intf
=
en
.
nextElement
();
for
(
Enumeration
<
InetAddress
>
enumIpAddr
=
intf
.
getInetAddresses
();
enumIpAddr
.
hasMoreElements
();)
{
InetAddress
inetAddress
=
enumIpAddr
.
nextElement
();
if
(!
inetAddress
.
isLoopbackAddress
())
{
return
inetAddress
.
getHostAddress
().
toString
();
}
}
}
}
catch
(
SocketException
ex
)
{
Log
.
e
(
"getLocalIpAddress"
,
ex
.
toString
());
}
}
catch
(
SocketException
ex
)
{
ex
.
printStackTrace
();
return
null
;
}
return
localIP
;
}
/**
* 显示视频debug信息
*/
public
static
void
showDbgMsg
(
String
level
,
String
data
){
Intent
intent
=
new
Intent
(
StatusInfoView
.
DBG_MSG
);
intent
.
putExtra
(
StatusInfoView
.
DBG_LEVEL
,
level
);
intent
.
putExtra
(
StatusInfoView
.
DBG_DATA
,
data
);
LocalBroadcastManager
.
getInstance
(
EasyApplication
.
getEasyApplication
()).
sendBroadcast
(
intent
);
}
}
Android/app/src/main/java/org/easydarwin/easyipcamera/view/StatusInfoView.java
浏览文件 @
4d59186e
package
org.easydarwin.easyipcamera.view
;
import
android.content.BroadcastReceiver
;
import
android.content.Context
;
import
android.content.Intent
;
import
android.content.IntentFilter
;
import
android.graphics.Canvas
;
import
android.graphics.Color
;
import
android.graphics.Paint
;
import
android.os.Handler
;
import
android.support.v4.content.LocalBroadcastManager
;
import
android.util.AttributeSet
;
import
android.view.View
;
import
android.view.ViewGroup
;
...
...
@@ -24,14 +28,12 @@ public class StatusInfoView extends View {
public
StatusInfoView
(
Context
context
)
{
super
(
context
);
mContext
=
context
;
mInfoList
=
new
ArrayList
<
StatusInfo
>();
mInfoList
.
clear
();
init
();
}
public
StatusInfoView
(
Context
context
,
AttributeSet
attr
)
{
super
(
context
,
attr
);
mContext
=
context
;
mInfoList
=
new
ArrayList
<
StatusInfo
>();
mInfoList
.
clear
();
init
();
}
public
static
StatusInfoView
getInstence
(){
...
...
@@ -43,6 +45,18 @@ public class StatusInfoView extends View {
handler
.
postDelayed
(
runnable
,
1000
);
}
private
void
init
(){
mInfoList
=
new
ArrayList
<
StatusInfo
>();
mInfoList
.
clear
();
final
IntentFilter
inf
=
new
IntentFilter
(
DBG_MSG
);
LocalBroadcastManager
.
getInstance
(
mContext
).
registerReceiver
(
mReceiver
,
inf
);
}
public
void
uninit
(){
LocalBroadcastManager
.
getInstance
(
mContext
).
unregisterReceiver
(
mReceiver
);
}
public
void
addInfoMsg
(
StatusInfo
info
){
mInfoList
.
add
(
info
);
}
...
...
@@ -86,6 +100,29 @@ public class StatusInfoView extends View {
}
}
//BroadCast
public
static
final
String
DBG_MSG
=
"dbg-msg"
;
public
static
final
String
DBG_LEVEL
=
"dbg-level"
;
public
static
final
String
DBG_DATA
=
"dbg-datas"
;
public
static
class
DbgLevel
{
public
static
final
String
DBG_LEVEL_INFO
=
"Info"
;
public
static
final
String
DBG_LEVEL_WARN
=
"Warn"
;
}
private
BroadcastReceiver
mReceiver
=
new
BroadcastReceiver
()
{
@Override
public
void
onReceive
(
Context
context
,
Intent
intent
)
{
if
(
DBG_MSG
.
equals
(
intent
.
getAction
()))
{
final
String
msg
=
intent
.
getStringExtra
(
DBG_DATA
);
final
String
level
=
intent
.
getStringExtra
(
DBG_LEVEL
);
if
(!
level
.
isEmpty
()
&&
!
msg
.
isEmpty
())
{
StatusInfo
info
=
new
StatusInfo
(
level
,
msg
);
addInfoMsg
(
info
);
}
}
}
};
public
static
class
StatusInfo
{
String
level
;
String
values
;
...
...
Android/app/src/main/res/layout/activity_main.xml
浏览文件 @
4d59186e
...
...
@@ -3,7 +3,7 @@
xmlns:tools=
"http://schemas.android.com/tools"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
tools:context=
"
org.easydarwin.easyipcamera
.activity.StreameActivity"
>
tools:context=
".activity.StreameActivity"
>
<SurfaceView
android:id=
"@+id/sv_surfaceview"
...
...
@@ -28,63 +28,63 @@
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
/>
<
Button
android:
id=
"@+id/btn_switch
"
android:
layout_width=
"wrap_content
"
android:
layout_height=
"wrap_content
"
<
LinearLayout
android:
layout_width=
"match_parent
"
android:
id=
"@+id/option_bar_container
"
android:
orientation=
"vertical
"
android:layout_alignParentBottom=
"true"
android:text=
"开始"
android:background=
"@drawable/button_selector"
android:textColor=
"#ffffff"
/>
android:layout_height=
"wrap_content"
>
<Button
android:id=
"@+id/btn_setting"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_toRightOf=
"@+id/btn_switch"
android:layout_alignParentBottom=
"true"
android:layout_marginLeft=
"5dp"
android:background=
"@drawable/button_selector"
android:text=
"设置"
android:visibility=
"visible"
android:textColor=
"#ffffff"
/>
<Button
android:id=
"@+id/btn_record"
android:visibility=
"gone"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_toRightOf=
"@+id/btn_setting"
android:layout_alignParentBottom=
"true"
android:layout_marginLeft=
"5dp"
android:background=
"@drawable/button_selector"
android:text=
"录像"
android:textColor=
"#ffffff"
/>
<Button
android:id=
"@+id/btn_audio"
android:visibility=
"gone"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_toRightOf=
"@+id/btn_record"
android:layout_alignParentBottom=
"true"
android:layout_marginLeft=
"5dp"
android:background=
"@drawable/button_selector"
android:text=
"静音"
android:textColor=
"#ffffff"
/>
<Button
android:id=
"@+id/btn_switchCamera"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_toRightOf=
"@+id/btn_audio"
android:layout_alignParentBottom=
"true"
android:layout_marginLeft=
"5dp"
android:background=
"@drawable/button_selector"
android:text=
"切换"
android:textColor=
"#ffffff"
/>
<LinearLayout
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
>
<Button
android:id=
"@+id/btn_switch"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_alignParentBottom=
"true"
android:text=
"推送摄像头"
android:background=
"@drawable/button_selector"
android:textColor=
"#ffffff"
/>
<Button
android:id=
"@+id/btn_switchCamera"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_toRightOf=
"@+id/btn_audio"
android:layout_alignParentBottom=
"true"
android:layout_marginLeft=
"5dp"
android:background=
"@drawable/button_selector"
android:text=
"切换"
android:textColor=
"#ffffff"
/>
<Button
android:id=
"@+id/push_screen"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginLeft=
"5dp"
android:layout_alignParentBottom=
"true"
android:text=
"推送屏幕"
android:background=
"@drawable/button_selector"
android:textColor=
"#ffffff"
/>
<Button
android:id=
"@+id/btn_setting"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_toRightOf=
"@+id/btn_switch"
android:layout_alignParentBottom=
"true"
android:layout_marginLeft=
"5dp"
android:background=
"@drawable/button_selector"
android:text=
"设置"
android:visibility=
"visible"
android:textColor=
"#ffffff"
/>
</LinearLayout>
</LinearLayout>
<TextView
android:id=
"@+id/txt_stream_address"
android:textColor=
"#ff0000"
android:layout_above=
"@+id/
btn_switch
"
android:layout_above=
"@+id/
option_bar_container
"
android:padding=
"5dp"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
/>
...
...
Android/app/src/main/res/layout/activity_setting.xml
浏览文件 @
4d59186e
...
...
@@ -5,7 +5,7 @@
android:layout_height=
"match_parent"
android:orientation=
"vertical"
android:padding=
"20dp"
tools:context=
"
org.easydarwin.easyipcamera
.activity.SettingActivity"
>
tools:context=
".activity.SettingActivity"
>
<TextView
...
...
@@ -19,8 +19,8 @@
android:id=
"@+id/edt_server_port"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:hint=
"EasyDarwin端口(默认554)"
android:text=
"554"
android:hint=
"EasyDarwin端口(默认
8
554)"
android:text=
"
8
554"
android:textColorHint=
"#80000000"
/>
<EditText
...
...
@@ -30,6 +30,15 @@
android:hint=
"直播流ID"
android:textColorHint=
"#80000000"
/>
<CheckBox
android:id=
"@+id/use_x264_encode"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:checked=
"false"
android:paddingBottom=
"@dimen/activity_vertical_margin"
android:paddingTop=
"@dimen/activity_vertical_margin"
android:text=
"使用软编码"
/>
<Button
android:id=
"@+id/btn_save"
android:layout_width=
"match_parent"
...
...
Android/app/src/main/res/layout/activity_splash.xml
浏览文件 @
4d59186e
...
...
@@ -29,6 +29,6 @@
android:layout_centerHorizontal=
"true"
android:layout_marginBottom=
"10dp"
android:gravity=
"center"
android:text=
"Copyright 2012-201
6
www.EasyDarwin.org"
/>
android:text=
"Copyright 2012-201
7
www.EasyDarwin.org"
/>
</RelativeLayout>
\ No newline at end of file
Android/build.gradle
浏览文件 @
4d59186e
...
...
@@ -5,7 +5,7 @@ buildscript {
jcenter
()
}
dependencies
{
classpath
'com.android.tools.build:gradle:2.
1.2
'
classpath
'com.android.tools.build:gradle:2.
2.3
'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
...
...
Android/gradle.properties
浏览文件 @
4d59186e
...
...
@@ -5,13 +5,13 @@
#
# Specifies the JVM arguments used for the daemon process.
# The setting is particularly useful for tweaking memory settings.
# Default value: -Xmx1024
8
m -XX:MaxPermSize=256m
# Default value: -Xmx1024m -XX:MaxPermSize=256m
# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8
#
# When configured, Gradle will run in incubating parallel mode.
# This option should only be used with decoupled projects. More details, visit
# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
# org.gradle.parallel=true
#
Mon Aug 08 19:43:17 CST 2016
#
Fri Feb 10 23:01:49 CST 2017
systemProp.http.proxyHost
=
mirrors.neusoft.edu.cn
systemProp.http.proxyPort
=
80
Android/gradle/wrapper/gradle-wrapper.properties
浏览文件 @
4d59186e
#Mon Dec 2
8 10:00:20 PST 2015
#Mon Dec 2
6 23:04:21 CST 2016
distributionBase
=
GRADLE_USER_HOME
distributionPath
=
wrapper/dists
zipStoreBase
=
GRADLE_USER_HOME
zipStorePath
=
wrapper/dists
distributionUrl
=
https
\:
//services.gradle.org/distributions/gradle-2.1
0
-all.zip
distributionUrl
=
https
\:
//services.gradle.org/distributions/gradle-2.1
4.1
-all.zip
EasyIPCamera_RTSP/libEasyRTSPClient/Include/EasyRTSPClientAPI.h
浏览文件 @
4d59186e
...
...
@@ -28,7 +28,11 @@ extern "C"
Easy_API
int
Easy_APICALL
EasyRTSP_GetErrCode
(
Easy_RTSP_Handle
handle
);
/* 激活 */
#ifdef ANDROID
Easy_API
int
Easy_APICALL
EasyRTSP_Activate
(
char
*
license
,
char
*
userPtr
);
#else
Easy_API
int
Easy_APICALL
EasyRTSP_Activate
(
char
*
license
);
#endif
/* 创建RTSPClient句柄 返回0表示成功,返回非0表示失败 */
Easy_API
int
Easy_APICALL
EasyRTSP_Init
(
Easy_RTSP_Handle
*
handle
);
...
...
@@ -40,7 +44,7 @@ extern "C"
Easy_API
int
Easy_APICALL
EasyRTSP_SetCallback
(
Easy_RTSP_Handle
handle
,
RTSPSourceCallBack
_callback
);
/* 打开网络流 */
Easy_API
int
Easy_APICALL
EasyRTSP_OpenStream
(
Easy_RTSP_Handle
handle
,
int
_channelid
,
char
*
_url
,
RTP_CONNECT_TYPE
_connType
,
unsigned
int
_mediaType
,
char
*
_username
,
char
*
_password
,
void
*
userPtr
,
int
_reconn
/*1000表示长连接,即如果网络断开自动重连, 其它值为连接次数*/
,
int
outRtpPacket
/*默认为0,即回调输出完整的帧, 如果为1,则输出RTP包*/
,
int
heartbeatType
/*0x00:不发送心跳 0x01:OPTIONS 0x02:GET_PARAMETER*/
,
int
_verbosity
/*日志打印输出等级,0表示不输出*/
);
Easy_API
int
Easy_APICALL
EasyRTSP_OpenStream
(
Easy_RTSP_Handle
handle
,
int
_channelid
,
char
*
_url
,
EASY_
RTP_CONNECT_TYPE
_connType
,
unsigned
int
_mediaType
,
char
*
_username
,
char
*
_password
,
void
*
userPtr
,
int
_reconn
/*1000表示长连接,即如果网络断开自动重连, 其它值为连接次数*/
,
int
outRtpPacket
/*默认为0,即回调输出完整的帧, 如果为1,则输出RTP包*/
,
int
heartbeatType
/*0x00:不发送心跳 0x01:OPTIONS 0x02:GET_PARAMETER*/
,
int
_verbosity
/*日志打印输出等级,0表示不输出*/
);
/* 关闭网络流 */
Easy_API
int
Easy_APICALL
EasyRTSP_CloseStream
(
Easy_RTSP_Handle
handle
);
...
...
EasyIPCamera_RTSP/libEasyRTSPClient/Lib/libEasyRTSPClient.dll
浏览文件 @
4d59186e
无法预览此类型文件
EasyIPCamera_RTSP/libEasyRTSPClient/Lib/libEasyRTSPClient.lib
浏览文件 @
4d59186e
无法预览此类型文件
EasyIPCamera_RTSP/main.cpp
浏览文件 @
4d59186e
...
...
@@ -12,6 +12,20 @@
#include "EasyRTSPClientAPI.h"
#include "GetVPSSPSPPS.h"
#ifdef _WIN32
#define KEY_EASYIPCAMERA "6D72754B7A4969576B5A7341344B6859703163667065704659584E35535642445957316C636D4666556C52545543356C65475658444661672F365867523246326157346D516D466962334E68514449774D545A4659584E355247467964326C75564756686257566863336B3D"
#define KEY_EASYRTSPCLIENT "79393674363469576B5A7341344B6859703163667065704659584E35535642445957316C636D4666556C52545543356C65475658444661672F365867523246326157346D516D466962334E68514449774D545A4659584E355247467964326C75564756686257566863336B3D"
#elif def _ARM
#define KEY_EASYIPCAMERA "6D72754B7A502B2B72624941344B6859703163667065356C59584E356158426A5957316C636D4666636E527A6346634D5671442F7065424859585A7062695A4359574A76633246414D6A41784E6B566863336C4559584A33615735555A5746745A57467A65513D3D"
#define KEY_EASYRTSPCLIENT "79393674362F2B2B72624941344B6859703163667065356C59584E356158426A5957316C636D4666636E527A6346634D5671442F7065424859585A7062695A4359574A76633246414D6A41784E6B566863336C4559584A33615735555A5746745A57467A65513D3D"
#else //x86 linux
#define KEY_EASYIPCAMERA "6D72754B7A4A4F576B596F41344B6859703163667065356C59584E356158426A5957316C636D4666636E527A6346634D5671442F7065424859585A7062695A4359574A76633246414D6A41784E6B566863336C4559584A33615735555A5746745A57467A65513D3D"
#define KEY_EASYRTSPCLIENT "7939367436354F576B596F41344B6859703163667065356C59584E356158426A5957316C636D4666636E527A6346634D5671442F7065424859585A7062695A4359574A76633246414D6A41784E6B566863336C4559584A33615735555A5746745A57467A65513D3D"
#endif
#define RTSP_SOURCE1 "rtsp://admin:admin@192.168.2.100/11"
#define RTSP_SOURCE2 "rtsp://admin:admin@192.168.2.100/33"
typedef
enum
__SOURCE_TYPE_ENUM_T
{
SOURCE_TYPE_FILE
=
0x01
,
...
...
@@ -166,7 +180,7 @@ Easy_I32 __EasyIPCamera_Callback(Easy_I32 channelId, EASY_IPCAMERA_STATE_T chann
EasyRTSP_Init
(
&
pChannel
[
channelId
].
rtspHandle
);
EasyRTSP_SetCallback
(
pChannel
[
channelId
].
rtspHandle
,
__RTSPSourceCallBack
);
EasyRTSP_OpenStream
(
pChannel
[
channelId
].
rtspHandle
,
channelId
,
pChannel
[
channelId
].
source_uri
,
RTP_OVER_TCP
,
1
,
pChannel
[
channelId
].
username
,
pChannel
[
channelId
].
password
,
(
void
*
)
&
pChannel
[
channelId
],
1000
,
0
,
0
,
1
);
EasyRTSP_OpenStream
(
pChannel
[
channelId
].
rtspHandle
,
channelId
,
pChannel
[
channelId
].
source_uri
,
EASY_
RTP_OVER_TCP
,
1
,
pChannel
[
channelId
].
username
,
pChannel
[
channelId
].
password
,
(
void
*
)
&
pChannel
[
channelId
],
1000
,
0
,
0
,
1
);
}
printf
(
"[channel %d] Get media info...
\n
"
,
channelId
);
...
...
@@ -236,14 +250,14 @@ int main()
if
(
i
==
0
)
{
channel
[
i
].
sourceType
=
SOURCE_TYPE_RTSP
;
strcpy
(
channel
[
i
].
source_uri
,
"rtsp://admin:admin@192.168.66.222/11"
);
strcpy
(
channel
[
i
].
source_uri
,
RTSP_SOURCE1
);
strcpy
(
channel
[
i
].
username
,
"admin"
);
strcpy
(
channel
[
i
].
password
,
"admin"
);
}
else
if
(
i
==
1
)
{
channel
[
i
].
sourceType
=
SOURCE_TYPE_RTSP
;
strcpy
(
channel
[
i
].
source_uri
,
"rtsp://admin:admin@192.168.66.222/33"
);
strcpy
(
channel
[
i
].
source_uri
,
RTSP_SOURCE2
);
strcpy
(
channel
[
i
].
username
,
"admin"
);
strcpy
(
channel
[
i
].
password
,
"admin"
);
}
...
...
@@ -252,7 +266,7 @@ int main()
}
//进程名: EasyIPCamera_RTSP.exe
int
activate_ret
=
EasyRTSP_Activate
(
"6A59754D6A3469576B5A754134703958714741634575704659584E35535642445957316C636D4666556C52545543356C65475658444661672F704C67523246326157346D516D466962334E68514449774D545A4659584E355247467964326C75564756686257566863336B3D"
);
int
activate_ret
=
EasyRTSP_Activate
(
KEY_EASYRTSPCLIENT
);
if
(
activate_ret
<
0
)
{
printf
(
"激活libEasyRTSPClient失败: %d
\n
"
,
activate_ret
);
...
...
@@ -266,7 +280,7 @@ int main()
strcpy
(
liveChannel
[
i
].
name
,
channel
[
i
].
name
);
}
activate_ret
=
EasyIPCamera_Activate
(
"6D7061506E4969576B5A734132786459702B676A6B75704659584E35535642445957316C636D4666556C52545543356C65475658444661672F704C67523246326157346D516D466962334E68514449774D545A4659584E355247467964326C75564756686257566863336B3D"
);
activate_ret
=
EasyIPCamera_Activate
(
KEY_EASYIPCAMERA
);
if
(
activate_ret
<
0
)
{
printf
(
"激活libEasyIPCamera失败: %d
\n
"
,
activate_ret
);
...
...
EasyIPCamera_Win/ServerManager.cpp
浏览文件 @
4d59186e
...
...
@@ -430,7 +430,7 @@ int __EasyIPCamera_Callback(Easy_I32 channelId, EASY_IPCAMERA_STATE_T channelSta
//开始RTSP服务
int
CServerManager
::
StartServer
(
int
listenport
,
char
*
username
,
char
*
password
,
LIVE_CHANNEL_INFO_T
*
channelInfo
,
Easy_U32
channelNum
)
{
EasyIPCamera_Activate
(
"6D7
061506E4969576B5A734132786459702B676A6B75744659584E35535642445957316C636D466656326C754C6D56345A536C58444661672F704C
67523246326157346D516D466962334E68514449774D545A4659584E355247467964326C75564756686257566863336B3D"
);
EasyIPCamera_Activate
(
"6D7
2754B7A4969576B5A7341344B6859703163667065744659584E35535642445957316C636D466656326C754C6D56345A577858444661672F3658
67523246326157346D516D466962334E68514449774D545A4659584E355247467964326C75564756686257566863336B3D"
);
//EasyIPCamera_Callback callback, void *userptr,
int
ret
=
EasyIPCamera_Startup
(
listenport
,
AUTHENTICATION_TYPE_BASIC
,
(
char
*
)
""
,
(
Easy_U8
*
)
username
,
(
Easy_U8
*
)
password
,
__EasyIPCamera_Callback
,
this
,
channelInfo
,
channelNum
);
...
...
Include/EasyTypes.h
浏览文件 @
4d59186e
...
...
@@ -62,96 +62,96 @@ typedef int Easy_Error;
typedef
enum
__EASY_ACTIVATE_ERR_CODE_ENUM
{
EASY_ACTIVATE_INVALID_KEY
=
-
1
,
//
无效
Key
EASY_ACTIVATE_TIME_ERR
=
-
2
,
//
时间错误
EASY_ACTIVATE_PROCESS_NAME_LEN_ERR
=
-
3
,
//
进程名称长度不匹配
EASY_ACTIVATE_PROCESS_NAME_ERR
=
-
4
,
//
进程名称不匹配
EASY_ACTIVATE_VALIDITY_PERIOD_ERR
=
-
5
,
//
有效期校验不一致
EASY_ACTIVATE_PLATFORM_ERR
=
-
6
,
//
平台不匹配
EASY_ACTIVATE_COMPANY_ID_LEN_ERR
=
-
7
,
//
授权使用商不匹配
EASY_ACTIVATE_SUCCESS
=
0
,
//
激活成功
EASY_ACTIVATE_INVALID_KEY
=
-
1
,
//
ÎÞЧ
Key
EASY_ACTIVATE_TIME_ERR
=
-
2
,
//
ʱ¼ä´íÎó
EASY_ACTIVATE_PROCESS_NAME_LEN_ERR
=
-
3
,
//
½ø³ÌÃû³Æ³¤¶È²»Æ¥Åä
EASY_ACTIVATE_PROCESS_NAME_ERR
=
-
4
,
//
½ø³ÌÃû³Æ²»Æ¥Åä
EASY_ACTIVATE_VALIDITY_PERIOD_ERR
=
-
5
,
//
ÓÐЧÆÚУÑé²»Ò»ÖÂ
EASY_ACTIVATE_PLATFORM_ERR
=
-
6
,
//
ƽ̨²»Æ¥Åä
EASY_ACTIVATE_COMPANY_ID_LEN_ERR
=
-
7
,
//
ÊÚȨʹÓÃÉ̲»Æ¥Åä
EASY_ACTIVATE_SUCCESS
=
0
,
//
¼¤»î³É¹¦
}
EASY_ACTIVATE_ERR_CODE_ENUM
;
/*
视频编码
*/
/*
ÊÓƵ±àÂë
*/
#define EASY_SDK_VIDEO_CODEC_H264 0x1C
/* H264 */
#define EASY_SDK_VIDEO_CODEC_H265 0x48323635
/* 1211250229 */
#define EASY_SDK_VIDEO_CODEC_MJPEG 0x08
/* MJPEG */
#define EASY_SDK_VIDEO_CODEC_MPEG4 0x0D
/* MPEG4 */
/*
音频编码
*/
/*
ÒôƵ±àÂë
*/
#define EASY_SDK_AUDIO_CODEC_AAC 0x15002
/* AAC */
#define EASY_SDK_AUDIO_CODEC_G711U 0x10006
/* G711 ulaw*/
#define EASY_SDK_AUDIO_CODEC_G711A 0x10007
/* G711 alaw*/
#define EASY_SDK_AUDIO_CODEC_G726 0x1100B
/* G726 */
/*
音视频帧标识
*/
#define EASY_SDK_VIDEO_FRAME_FLAG 0x00000001
/*
视频帧标志
*/
#define EASY_SDK_AUDIO_FRAME_FLAG 0x00000002
/*
音频帧标志
*/
#define EASY_SDK_EVENT_FRAME_FLAG 0x00000004
/*
事件帧标志
*/
#define EASY_SDK_RTP_FRAME_FLAG 0x00000008
/* RTP
帧标志
*/
#define EASY_SDK_SDP_FRAME_FLAG 0x00000010
/* SDP
帧标志
*/
#define EASY_SDK_MEDIA_INFO_FLAG 0x00000020
/*
媒体类型标志
*/
/*
ÒôÊÓƵ֡±êʶ
*/
#define EASY_SDK_VIDEO_FRAME_FLAG 0x00000001
/*
ÊÓƵ֡±êÖ¾
*/
#define EASY_SDK_AUDIO_FRAME_FLAG 0x00000002
/*
ÒôƵ֡±êÖ¾
*/
#define EASY_SDK_EVENT_FRAME_FLAG 0x00000004
/*
ʼþÖ¡±êÖ¾
*/
#define EASY_SDK_RTP_FRAME_FLAG 0x00000008
/* RTP
Ö¡±êÖ¾
*/
#define EASY_SDK_SDP_FRAME_FLAG 0x00000010
/* SDP
Ö¡±êÖ¾
*/
#define EASY_SDK_MEDIA_INFO_FLAG 0x00000020
/*
ýÌåÀàÐͱêÖ¾
*/
/*
视频关键字标识
*/
#define EASY_SDK_VIDEO_FRAME_I 0x01
/* I
帧
*/
#define EASY_SDK_VIDEO_FRAME_P 0x02
/* P
帧
*/
#define EASY_SDK_VIDEO_FRAME_B 0x03
/* B
帧
*/
/*
ÊÓƵ¹Ø¼ü×Ö±êʶ
*/
#define EASY_SDK_VIDEO_FRAME_I 0x01
/* I
Ö¡
*/
#define EASY_SDK_VIDEO_FRAME_P 0x02
/* P
Ö¡
*/
#define EASY_SDK_VIDEO_FRAME_B 0x03
/* B
Ö¡
*/
#define EASY_SDK_VIDEO_FRAME_J 0x04
/* JPEG */
/*
连接类型
*/
typedef
enum
__RTP_CONNECT_TYPE
/*
连接类型 *
/
typedef
enum
__
EASY_
RTP_CONNECT_TYPE
{
RTP_OVER_TCP
=
0x01
,
/* RTP Over TCP */
RTP_OVER_UDP
/* RTP Over UDP */
}
RTP_CONNECT_TYPE
;
EASY_
RTP_OVER_TCP
=
0x01
,
/* RTP Over TCP */
EASY_
RTP_OVER_UDP
/* RTP Over UDP */
}
EASY_
RTP_CONNECT_TYPE
;
/*
媒体信息
*/
/*
ýÌåÐÅÏ¢
*/
typedef
struct
__EASY_MEDIA_INFO_T
{
Easy_U32
u32VideoCodec
;
/*
视频编码类型
*/
Easy_U32
u32VideoFps
;
/*
视频帧率
*/
Easy_U32
u32AudioCodec
;
/*
音频编码类型
*/
Easy_U32
u32AudioSamplerate
;
/*
音频采样率
*/
Easy_U32
u32AudioChannel
;
/*
音频通道数
*/
Easy_U32
u32AudioBitsPerSample
;
/*
音频采样精度
*/
Easy_U32
u32VpsLength
;
/*
视频vps帧长度
*/
Easy_U32
u32SpsLength
;
/*
视频sps帧长度
*/
Easy_U32
u32PpsLength
;
/*
视频pps帧长度
*/
Easy_U32
u32SeiLength
;
/*
视频sei帧长度
*/
Easy_U8
u8Vps
[
128
];
/* 视频vps帧内容
*/
Easy_U8
u8Sps
[
128
];
/* 视频sps帧内容
*/
Easy_U8
u8Pps
[
36
];
/* 视频sps帧内容
*/
Easy_U8
u8Sei
[
36
];
/* 视频sei帧内容
*/
Easy_U32
u32VideoCodec
;
/*
ÊÓƵ±àÂëÀàÐÍ
*/
Easy_U32
u32VideoFps
;
/*
ÊÓƵ֡ÂÊ
*/
Easy_U32
u32AudioCodec
;
/*
ÒôƵ±àÂëÀàÐÍ
*/
Easy_U32
u32AudioSamplerate
;
/*
ÒôƵ²ÉÑùÂÊ
*/
Easy_U32
u32AudioChannel
;
/*
ÒôƵͨµÀÊý
*/
Easy_U32
u32AudioBitsPerSample
;
/*
ÒôƵ²ÉÑù¾«¶È
*/
Easy_U32
u32VpsLength
;
/*
ÊÓƵvpsÖ¡³¤¶È
*/
Easy_U32
u32SpsLength
;
/*
ÊÓƵspsÖ¡³¤¶È
*/
Easy_U32
u32PpsLength
;
/*
ÊÓƵppsÖ¡³¤¶È
*/
Easy_U32
u32SeiLength
;
/*
ÊÓƵseiÖ¡³¤¶È
*/
Easy_U8
u8Vps
[
255
];
/* ÊÓƵvpsÖ¡ÄÚÈÝ
*/
Easy_U8
u8Sps
[
255
];
/* ÊÓƵspsÖ¡ÄÚÈÝ
*/
Easy_U8
u8Pps
[
128
];
/* ÊÓƵspsÖ¡ÄÚÈÝ
*/
Easy_U8
u8Sei
[
128
];
/* ÊÓƵseiÖ¡ÄÚÈÝ
*/
}
EASY_MEDIA_INFO_T
;
/*
帧信息
*/
/*
Ö¡ÐÅÏ¢
*/
typedef
struct
{
unsigned
int
codec
;
/*
音视频格式
*/
unsigned
int
codec
;
/*
ÒôÊÓƵ¸ñʽ
*/
unsigned
int
type
;
/*
视频帧类型
*/
unsigned
char
fps
;
/*
视频帧率
*/
unsigned
short
width
;
/*
视频宽
*/
unsigned
short
height
;
/*
视频高
*/
unsigned
int
type
;
/*
ÊÓƵ֡ÀàÐÍ
*/
unsigned
char
fps
;
/*
ÊÓƵ֡ÂÊ
*/
unsigned
short
width
;
/*
ÊÓƵ¿í
*/
unsigned
short
height
;
/*
ÊÓƵ¸ß
*/
unsigned
int
reserved1
;
/*
保留参数
1 */
unsigned
int
reserved2
;
/*
保留参数
2 */
unsigned
int
reserved1
;
/*
±£Áô²ÎÊý
1 */
unsigned
int
reserved2
;
/*
±£Áô²ÎÊý
2 */
unsigned
int
sample_rate
;
/*
音频采样率
*/
unsigned
int
channels
;
/*
音频声道数
*/
unsigned
int
bits_per_sample
;
/*
音频采样精度
*/
unsigned
int
sample_rate
;
/*
ÒôƵ²ÉÑùÂÊ
*/
unsigned
int
channels
;
/*
ÒôƵÉùµÀÊý
*/
unsigned
int
bits_per_sample
;
/*
ÒôƵ²ÉÑù¾«¶È
*/
unsigned
int
length
;
/*
音视频帧大小
*/
unsigned
int
timestamp_usec
;
/*
时间戳,微妙
*/
unsigned
int
timestamp_sec
;
/*
时间戳 秒
*/
unsigned
int
length
;
/*
ÒôÊÓƵ֡´óС
*/
unsigned
int
timestamp_usec
;
/*
ʱ¼ä´Á,΢Ãî
*/
unsigned
int
timestamp_sec
;
/*
ʱ¼ä´Á Ãë
*/
float
bitrate
;
/*
比特率
*/
float
losspacket
;
/*
丢包率
*/
float
bitrate
;
/*
±ÈÌØÂÊ
*/
float
losspacket
;
/*
¶ª°üÂÊ
*/
}
RTSP_FRAME_INFO
;
#endif
Lib/hisiv100/libeasyipcamera.a
浏览文件 @
4d59186e
无法预览此类型文件
Lib/hisiv100_shared/libeasyipcamera.so
浏览文件 @
4d59186e
无法预览此类型文件
Lib/hisiv200/libeasyipcamera.a
浏览文件 @
4d59186e
无法预览此类型文件
Lib/hisiv200_shared/libeasyipcamera.so
浏览文件 @
4d59186e
无法预览此类型文件
Lib/hisiv300/libeasyipcamera.a
浏览文件 @
4d59186e
无法预览此类型文件
Lib/hisiv300_shared/libeasyipcamera.so
浏览文件 @
4d59186e
无法预览此类型文件
Lib/hisiv400/libeasyipcamera.a
浏览文件 @
4d59186e
无法预览此类型文件
Lib/hisiv400_shared/libeasyipcamera.so
浏览文件 @
4d59186e
无法预览此类型文件
Lib/i386/libeasyipcamera.a
浏览文件 @
4d59186e
无法预览此类型文件
Lib/libEasyIPCamera.dll
浏览文件 @
4d59186e
无法预览此类型文件
Lib/libEasyIPCamera.lib
浏览文件 @
4d59186e
无法预览此类型文件
Lib/x64/libeasyipcamera.a
浏览文件 @
4d59186e
无法预览此类型文件
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录