Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
mirrorSimulator
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
李远洪
mirrorSimulator
Commits
6bf4e020
Commit
6bf4e020
authored
Jan 08, 2021
by
liyuanhong
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
小优化
parent
84c722f5
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
412 additions
and
0 deletions
+412
-0
lib/service/StreamH264Flv_bak.py
lib/service/StreamH264Flv_bak.py
+412
-0
No files found.
lib/service/StreamH264Flv_bak.py
0 → 100644
View file @
6bf4e020
#coding: utf-8
import
binascii
import
json
import
re
import
time
import
traceback
import
requests
from
lib.protocal.Protocal_1078
import
Protocal_1078
from
lib.socket.ClientSocket
import
ClientSocket
class
StreamH264Flv
():
def
__init__
(
self
):
self
.
isFileHead
=
0
# 读取文件的时候,是否是文件的开头 0:不是 1:是
self
.
readSize
=
1024
# 读取文件的大小
self
.
videoLastKeyTime
=
0
# Last I Frame Interval 该祯与上一个关键祯之间的时间间隔,单位毫秒(ms),当数据类型为非视频祯时,则没有该字段
self
.
videoLastTime
=
0
# Last Frame Interval 该祯与上一个祯之间的时间时间,单位毫秒(ms),当数据类型为非视频祯时,则没有该字段
self
.
sendDur
=
0.003
# 每发送一帧的间隔时间
self
.
client
=
None
self
.
mobile
=
"013146201117"
# 手机号
self
.
channel
=
1
# 频道号
self
.
isSendAudio
=
1
# 是否发送音频0:不发送 1:发送
self
.
isSend
=
0
# 是否发送消息 0:不发送 1:发送
self
.
isEndPush
=
0
# 是否结束推流 0:不结束 1:结束
# self.host = "10.100.11.125" # 开发环境
self
.
host
=
"10.100.12.3"
# 测试环境
self
.
port
=
1078
self
.
videoPath
=
"../../flv/bbb3.flv"
# 要推流的视频路劲
self
.
getGetPlayUrl
=
"http://10.100.11.110:9999/video/streamInfo"
# 获取推流播放地址的url
# self.getGetPlayUrl = "http://fb-test.vandyo.com/video/streamInfo" # 获取推流播放地址的url
self
.
isGetPlayUrl
=
0
# 是否已经获取了playUrl 0:没有 1:获取了
self
.
playUrl
=
""
# 视频播放地址
self
.
mainframe
=
None
# 图形界面主窗体,用于弹出对话框
self
.
logTextCtr
=
None
# 日志输出框,用于输出日志
self
.
pushStatusText
=
None
# 状态显示窗
self
.
multiPushStatus
=
0
# 多次推流标记, 0:该连接第一次推流 1:该连接第一次对流 2: 该连接第二次对流
self
.
timeStampSeek
=
0
# 时间搓偏移,推理完成后设置为最后一帧的时间搓值;循环推流的时候需要加上该值
self
.
isOpenVideoLog
=
0
# 是否开启视频日志 0:不开启 1:开启
self
.
isOpenAudioLog
=
0
# 是否开启音频日志 0:不开启 1:开启
self
.
protocal_1078
=
Protocal_1078
()
def
setMobile
(
self
,
data
):
self
.
mobile
=
data
def
setChannel
(
self
,
data
):
self
.
channel
=
data
def
setReadSize
(
self
,
data
):
self
.
readSize
=
data
def
setIsSendAudio
(
self
,
data
):
self
.
isSendAudio
=
data
def
setHost
(
self
,
data
):
self
.
host
=
data
def
setPort
(
self
,
data
):
self
.
port
=
data
def
setSendDur
(
self
,
data
):
self
.
sendDur
=
data
def
setVideoPath
(
self
,
data
):
self
.
videoPath
=
data
def
setIsSend
(
self
,
data
):
self
.
isSend
=
data
def
setIsEndPush
(
self
,
data
):
self
.
isEndPush
=
data
def
setMainFrame
(
self
,
data
):
self
.
mainframe
=
data
def
setLogTextCtr
(
self
,
data
):
self
.
logTextCtr
=
data
def
setPushStatusText
(
self
,
data
):
self
.
pushStatusText
=
data
def
setIsOpenVideoLog
(
self
,
data
):
self
.
isOpenVideoLog
=
data
def
setIsOpenAudioLog
(
self
,
data
):
self
.
isOpenAudioLog
=
data
####################################################
# socket 连接
####################################################
def
connectServer
(
self
):
socketObj
=
ClientSocket
()
socketObj
.
setHost
(
self
.
host
)
socketObj
.
setPort
(
self
.
port
)
self
.
client
=
socketObj
.
connect
()
# self.client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# self.client.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1) # 在客户端开启心跳
# self.client.connect((self.host, self.port))
####################################################
# socket 断开
####################################################
def
disConnectServer
(
self
):
self
.
client
.
close
()
####################################################
# 读取flv文件,并发送 (h264编码,并且音频为aac编码格式)
####################################################
def
readFlvAndSend
(
self
):
self
.
isSend
=
1
# 控制暂停或继续推流
self
.
isEndPush
=
0
self
.
isFileHead
=
0
timeStamp
=
0
doCount
=
0
# map 缓存
frameMap
=
{}
with
open
(
self
.
videoPath
,
'rb'
)
as
fi
:
con
=
fi
.
read
(
self
.
readSize
)
data
=
con
.
hex
()
if
self
.
isFileHead
==
0
:
data
=
data
[
18
:]
self
.
isFileHead
=
1
else
:
data
=
data
while
con
:
if
self
.
isEndPush
!=
0
:
break
else
:
if
self
.
isSend
==
1
:
if
len
(
data
)
<
30
:
con
=
fi
.
read
(
self
.
readSize
)
data
=
data
+
con
.
hex
()
else
:
tagSize
=
self
.
getAVTagSize
(
data
)
if
len
(
data
)
<
(
tagSize
*
2
+
30
):
con
=
fi
.
read
(
self
.
readSize
)
data
=
data
+
con
.
hex
()
else
:
tag
=
data
[:
tagSize
*
2
+
30
]
# flv tag
tagType
=
self
.
getTagType
(
tag
)
# flv tag 类型,是音频 还是视频
AVtag
=
tag
[
30
:]
# 音视频 tag
if
self
.
multiPushStatus
<
1
:
avTimeStamp
=
self
.
getAVTimeStamp
(
tag
)
#获取时间戳
timeStamp
=
avTimeStamp
if
tagType
==
"09"
:
timeStamp
=
timeStamp
+
self
.
getCompositionTime
(
AVtag
)
else
:
avTimeStamp
=
self
.
getAVTimeStamp
(
tag
)
+
self
.
timeStampSeek
# 获取时间戳
timeStamp
=
avTimeStamp
if
tagType
==
"09"
:
timeStamp
=
timeStamp
+
self
.
getCompositionTime
(
AVtag
)
if
doCount
<
30
:
frameMap
[
timeStamp
]
=
AVtag
doCount
=
doCount
+
1
else
:
frameMap
[
timeStamp
]
=
AVtag
frameArr
=
sorted
(
frameMap
.
keys
(),
reverse
=
True
)
AVtag
=
frameMap
.
pop
(
frameArr
.
pop
())
if
avTimeStamp
>
100
:
if
self
.
isGetPlayUrl
==
0
:
self
.
getPlayUrl
(
self
.
mobile
,
self
.
channel
)
self
.
isGetPlayUrl
=
1
if
tagType
==
"08"
:
# 音频
AVdata
=
AVtag
[
4
:]
# 音频数据
if
self
.
isSendAudio
==
1
:
frameInfo
=
self
.
getAudioFrame
(
AVtag
)
for
frame
in
frameInfo
[
"frames"
]:
self
.
sendAudioFrame
(
frame
,
avTimeStamp
)
elif
tagType
==
"09"
:
# 视频
AVdata
=
AVtag
[
10
:]
# 视频数据
frameInfo
=
self
.
getVideoFrame
(
AVtag
)
for
frame
in
frameInfo
[
"frames"
]:
self
.
sendVideoFrame
(
frame
,
avTimeStamp
,
AVtag
)
elif
tagType
==
"12"
:
# 脚本
AVdata
=
AVtag
# 脚本数据
else
:
AVdata
=
AVtag
data
=
data
[(
tagSize
*
2
+
30
):]
else
:
time
.
sleep
(
1
)
while
len
(
frameMap
)
>
0
:
frameArr
=
sorted
(
frameMap
.
keys
(),
reverse
=
True
)
AVtag
=
frameMap
.
pop
(
frameArr
.
pop
())
if
avTimeStamp
>
100
:
if
self
.
isGetPlayUrl
==
0
:
self
.
getPlayUrl
(
self
.
mobile
,
self
.
channel
)
self
.
isGetPlayUrl
=
1
if
tagType
==
"08"
:
# 音频
AVdata
=
AVtag
[
4
:]
# 音频数据
if
self
.
isSendAudio
==
1
:
frameInfo
=
self
.
getAudioFrame
(
AVtag
)
for
frame
in
frameInfo
[
"frames"
]:
self
.
sendAudioFrame
(
frame
,
avTimeStamp
)
elif
tagType
==
"09"
:
# 视频
AVdata
=
AVtag
[
10
:]
# 视频数据
frameInfo
=
self
.
getVideoFrame
(
AVtag
)
for
frame
in
frameInfo
[
"frames"
]:
self
.
sendVideoFrame
(
frame
,
avTimeStamp
,
AVtag
)
elif
tagType
==
"12"
:
# 脚本
AVdata
=
AVtag
# 脚本数据
else
:
AVdata
=
AVtag
data
=
data
[(
tagSize
*
2
+
30
):]
self
.
pushStatusText
.
SetValue
(
"已连网"
)
timeCur
=
self
.
getCurTime
()
self
.
multiPushStatus
=
self
.
multiPushStatus
+
1
self
.
timeStampSeek
=
timeStamp
+
1000
self
.
logTextCtr
.
WriteText
(
timeCur
+
"视频推流完,自动结束推流!
\n
"
)
# self.client.close()
####################################################
# 停止发送消息
####################################################
def
stopSend
(
self
):
self
.
isSend
=
0
####################################################
# 获取视频播放地址
####################################################
def
getPlayUrl
(
self
,
mobile
,
channel
):
res
=
requests
.
post
(
self
.
getGetPlayUrl
,
data
=
json
.
dumps
({
'devId'
:
mobile
,
'chan'
:
str
(
channel
)}))
.
text
res
=
json
.
loads
(
res
)
url
=
res
[
"data"
][
"url"
]
# url = self.replaceHost(res["data"]["url"],"video-test.vandyo.com:")
print
(
"播放地址:"
+
url
)
####################################################
# 替换url的host
####################################################
def
replaceHost
(
self
,
url
,
replaceWord
):
data
=
url
strinfo
=
re
.
compile
(
'(
\
d+.
\
d+.
\
d+.
\
d+.:)'
)
result
=
strinfo
.
sub
(
replaceWord
,
data
)
return
result
####################################################
# 发送视频帧
####################################################
def
sendVideoFrame
(
self
,
fra
,
timeStamp
,
avTag
):
self
.
protocal_1078
.
setSim
(
self
.
mobile
)
self
.
protocal_1078
.
setLogcC
(
self
.
channel
)
# avTimeStamp = timeStamp + self.getCompositionTime(avTag)
self
.
protocal_1078
.
setTime
(
timeStamp
)
frameType
=
fra
[
8
:
10
]
if
frameType
==
"65"
:
self
.
videoLastKeyTime
=
timeStamp
self
.
protocal_1078
.
setLastKeyTime
(
timeStamp
-
self
.
videoLastKeyTime
)
self
.
protocal_1078
.
setLastTime
(
timeStamp
-
self
.
videoLastTime
)
self
.
videoLastTime
=
timeStamp
else
:
self
.
protocal_1078
.
setLastKeyTime
(
timeStamp
-
self
.
videoLastKeyTime
)
self
.
protocal_1078
.
setLastTime
(
timeStamp
-
self
.
videoLastTime
)
self
.
videoLastTime
=
timeStamp
if
len
(
fra
)
%
2
!=
0
:
# 处理有问题的帧数据
print
(
"出现了视频问题帧,并自动修复..."
)
fra
=
fra
[:
len
(
fra
)
-
1
]
self
.
protocal_1078
.
setDataBody
(
fra
)
pkgs
=
self
.
protocal_1078
.
genPkgsByFrame
()
for
msg
in
pkgs
:
if
self
.
isOpenVideoLog
!=
0
:
print
(
"发送视频消息:"
+
msg
)
try
:
self
.
client
.
send
(
binascii
.
a2b_hex
(
msg
))
except
:
traceback
.
print_exc
()
print
(
msg
)
time
.
sleep
(
self
.
sendDur
)
####################################################
# 发送音频帧
####################################################
def
sendAudioFrame
(
self
,
fra
,
timeStamp
):
self
.
protocal_1078
.
setSim
(
self
.
mobile
)
self
.
protocal_1078
.
setLogcC
(
self
.
channel
)
self
.
protocal_1078
.
setTime
(
timeStamp
)
if
len
(
fra
)
%
2
!=
0
:
# 处理有问题的帧数据
print
(
"出现了视频问题帧,并自动修复..."
)
fra
=
fra
[:
len
(
fra
)
-
1
]
self
.
protocal_1078
.
setDataBody
(
fra
)
pkgs
=
self
.
protocal_1078
.
genAudioPkgsByFrame
()
for
msg
in
pkgs
:
if
self
.
isOpenAudioLog
!=
0
:
print
(
"发送音频消息:"
+
msg
)
self
.
client
.
send
(
binascii
.
a2b_hex
(
msg
))
time
.
sleep
(
self
.
sendDur
)
####################################################
# 获取TagType
# 0x08 音频
# 0x09 视频
# 0x12 脚本
####################################################
def
getTagType
(
self
,
tag
):
tagType
=
tag
[
8
:
10
]
return
tagType
####################################################
# 获取 flv tag 的数据长度,其实如图里 audio tag 头及其数据长度
####################################################
def
getAVTagSize
(
self
,
tag
):
tagSize
=
tag
[
10
:
16
]
tagSize
=
int
(
tagSize
,
16
)
return
tagSize
####################################################
# 获取相对时间戳 (音视频相对时间)
####################################################
def
getAVTimeStamp
(
self
,
tag
):
timeStamp
=
tag
[
16
:
22
]
timeStamp
=
tag
[
22
:
24
]
+
timeStamp
timeStamp
=
int
(
timeStamp
,
16
)
return
timeStamp
####################################################
# 获取音视频数据 (音视频头 + 数据部分)
####################################################
def
getAVData
(
self
,
tag
,
tagSize
):
flvData
=
tag
[
34
:(
tagSize
*
2
)]
lastData
=
tag
[(
tagSize
*
2
):]
return
flvData
,
lastData
####################################################
# 根据AVtag,获取视频帧数据
####################################################
def
getVideoFrame
(
self
,
AVTag
):
frameData
=
{}
frames
=
[]
# frameData["frameType"] = int(AVTag[:2],16) >> 4 # 视频帧类型
frameData
[
"codeId"
]
=
int
(
AVTag
[:
2
],
16
)
&
7
# 编码id ,7 为h264编码 (程序里默认都是h264)
frameData
[
"AVCPkgType"
]
=
int
(
AVTag
[
2
:
4
],
16
)
if
frameData
[
"AVCPkgType"
]
==
0
:
spsLen
=
int
(
AVTag
[
22
:
26
],
16
)
sps
=
"00000001"
+
AVTag
[
26
:
26
+
spsLen
*
2
]
ppsLen
=
int
(
AVTag
[
26
+
spsLen
*
2
+
2
:
26
+
spsLen
*
2
+
6
],
16
)
pps
=
"00000001"
+
AVTag
[
26
+
spsLen
*
2
+
6
:
26
+
spsLen
*
2
+
6
+
ppsLen
*
2
]
frames
.
append
(
sps
)
frames
.
append
(
pps
)
frameData
[
"frames"
]
=
frames
elif
frameData
[
"AVCPkgType"
]
==
1
:
dataLen
=
int
(
AVTag
[
10
:
18
],
16
)
frame
=
"00000001"
+
AVTag
[
18
:
18
+
dataLen
*
2
]
frames
.
append
(
frame
)
lastData
=
AVTag
[
18
+
dataLen
*
2
:]
if
len
(
lastData
)
!=
0
:
dataLen_65
=
int
(
AVTag
[
18
+
dataLen
*
2
:
18
+
dataLen
*
2
+
8
],
16
)
frame_65
=
"00000001"
+
AVTag
[
18
+
dataLen
*
2
+
8
:]
frames
.
append
(
frame_65
)
else
:
pass
frameData
[
"frames"
]
=
frames
elif
frameData
[
"AVCPkgType"
]
==
2
:
frameData
[
"frames"
]
=
[]
# print("2222222----------" + AVTag)
else
:
frameData
[
"frames"
]
=
[]
return
frameData
####################################################
# 获取视频帧的CompositionTime
####################################################
def
getCompositionTime
(
self
,
AVTag
):
AVCPkgType
=
int
(
AVTag
[
2
:
4
],
16
)
compositionTime
=
0
if
AVCPkgType
==
0
:
pass
else
:
compositionTime
=
int
(
AVTag
[
4
:
10
],
16
)
return
compositionTime
####################################################
# 根据AVtag,获取音频帧数据
####################################################
def
getAudioFrame
(
self
,
AVTag
):
frameData
=
{}
frames
=
[]
AVdata
=
AVTag
[
4
:]
cp_id_bit
=
0
<<
27
cp_id_start
=
0
<<
26
aac_frame_length
=
int
(
len
(
AVdata
)
/
2
+
7
)
<<
13
adts_buffer_funess
=
2047
<<
2
raw_data_frame
=
0
infoAac
=
cp_id_bit
+
cp_id_start
+
aac_frame_length
+
adts_buffer_funess
+
raw_data_frame
infoAac
=
hex
(
infoAac
)[
2
:]
while
len
(
infoAac
)
<
7
:
infoAac
=
"0"
+
infoAac
frame
=
"fff14c8"
+
infoAac
+
AVdata
frames
.
append
(
frame
)
frameData
[
"frames"
]
=
frames
return
frameData
####################################################
# 获取当前时间
####################################################
def
getCurTime
(
self
):
timeCur
=
int
(
time
.
time
()
*
1000
)
timeArray
=
time
.
localtime
(
timeCur
/
1000
)
timeCur
=
time
.
strftime
(
"
%
Y-
%
m-
%
d
%
H:
%
M:
%
S"
,
timeArray
)
timeCur
=
"["
+
timeCur
+
"] "
return
timeCur
if
__name__
==
"__main__"
:
obj
=
StreamH264Flv
()
obj
.
setSendDur
(
0.003
)
obj
.
setIsSendAudio
(
1
)
# obj.setMobile("013146201117")
obj
.
setMobile
(
"142043390091"
)
obj
.
setChannel
(
1
)
obj
.
setHost
(
"10.100.11.125"
)
# obj.setHost("video-test.vandyo.com")
obj
.
setPort
(
1078
)
obj
.
setVideoPath
(
"../../flv/aaa3.flv"
)
obj
.
connectServer
()
obj
.
readFlvAndSend
()
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment