Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
56586189
Commit
56586189
authored
Feb 11, 2023
by
ziyue
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完善h264/h265分帧逻辑,更新h264文件直播测试程序
parent
0773e79f
显示空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
156 行增加
和
11 行删除
+156
-11
api/include/mk_h264_splitter.h
+2
-1
api/source/mk_h264_splitter.cpp
+30
-4
api/tests/h264_media_server.c
+124
-6
没有找到文件。
api/include/mk_h264_splitter.h
查看文件 @
56586189
...
...
@@ -32,9 +32,10 @@ typedef void(API_CALL *on_mk_h264_splitter_frame)(void *user_data, mk_h264_split
* 创建h264分帧器
* @param cb 分帧回调函数
* @param user_data 回调用户数据指针
* @param is_h265 是否是265
* @return 分帧器对象
*/
API_EXPORT
mk_h264_splitter
API_CALL
mk_h264_splitter_create
(
on_mk_h264_splitter_frame
cb
,
void
*
user_data
);
API_EXPORT
mk_h264_splitter
API_CALL
mk_h264_splitter_create
(
on_mk_h264_splitter_frame
cb
,
void
*
user_data
,
int
is_h265
);
/**
* 删除h264分帧器
...
...
api/source/mk_h264_splitter.cpp
查看文件 @
56586189
...
...
@@ -10,13 +10,15 @@
#include "mk_h264_splitter.h"
#include "Http/HttpRequestSplitter.h"
#include "Extension/H264.h"
#include "Extension/H265.h"
using
namespace
mediakit
;
class
H264Splitter
:
public
HttpRequestSplitter
{
public
:
using
onH264
=
std
::
function
<
void
(
const
char
*
data
,
size_t
len
)
>
;
H264Splitter
(
)
=
default
;
H264Splitter
(
bool
h265
=
false
)
{
_h265
=
h265
;
}
~
H264Splitter
()
override
;
void
setOnSplitted
(
onH264
cb
);
...
...
@@ -25,7 +27,9 @@ protected:
const
char
*
onSearchPacketTail
(
const
char
*
data
,
size_t
len
)
override
;
private
:
bool
_h265
=
false
;
onH264
_cb
;
size_t
_search_pos
=
0
;
};
void
H264Splitter
::
setOnSplitted
(
H264Splitter
::
onH264
cb
)
{
...
...
@@ -43,7 +47,7 @@ ssize_t H264Splitter::onRecvHeader(const char *data, size_t len) {
return
0
;
}
const
char
*
H264Splitter
::
onSearchPacketTai
l
(
const
char
*
data
,
size_t
len
)
{
static
const
char
*
onSearchPacketTail_
l
(
const
char
*
data
,
size_t
len
)
{
for
(
size_t
i
=
2
;
len
>
2
&&
i
<
len
-
2
;
++
i
)
{
//判断0x00 00 01
if
(
data
[
i
]
==
0
&&
data
[
i
+
1
]
==
0
&&
data
[
i
+
2
]
==
1
)
{
...
...
@@ -57,11 +61,33 @@ const char *H264Splitter::onSearchPacketTail(const char *data, size_t len) {
return
nullptr
;
}
const
char
*
H264Splitter
::
onSearchPacketTail
(
const
char
*
data
,
size_t
len
)
{
auto
last_frame
=
data
+
_search_pos
;
auto
next_frame
=
onSearchPacketTail_l
(
last_frame
,
len
-
_search_pos
);
if
(
!
next_frame
)
{
return
nullptr
;
}
auto
last_frame_len
=
next_frame
-
last_frame
;
Frame
::
Ptr
frame
;
if
(
_h265
)
{
frame
=
std
::
make_shared
<
H265FrameNoCacheAble
>
((
char
*
)
last_frame
,
last_frame_len
,
0
,
0
,
prefixSize
(
last_frame
,
last_frame_len
));
}
else
{
frame
=
std
::
make_shared
<
H264FrameNoCacheAble
>
((
char
*
)
last_frame
,
last_frame_len
,
0
,
0
,
prefixSize
(
last_frame
,
last_frame_len
));
}
if
(
frame
->
decodeAble
())
{
_search_pos
=
0
;
return
next_frame
;
}
_search_pos
+=
last_frame_len
;
return
nullptr
;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////
API_EXPORT
mk_h264_splitter
API_CALL
mk_h264_splitter_create
(
on_mk_h264_splitter_frame
cb
,
void
*
user_data
)
{
API_EXPORT
mk_h264_splitter
API_CALL
mk_h264_splitter_create
(
on_mk_h264_splitter_frame
cb
,
void
*
user_data
,
int
is_h265
)
{
assert
(
cb
);
auto
ptr
=
new
H264Splitter
();
auto
ptr
=
new
H264Splitter
(
is_h265
);
ptr
->
setOnSplitted
([
cb
,
ptr
,
user_data
](
const
char
*
data
,
size_t
len
)
{
cb
(
user_data
,
reinterpret_cast
<
mk_h264_splitter
>
(
ptr
),
data
,
len
);
});
...
...
api/tests/h264_media_server.c
查看文件 @
56586189
...
...
@@ -36,9 +36,108 @@ static void on_h264_frame(void *user_data, mk_h264_splitter splitter, const char
mk_frame_unref
(
frame
);
}
//按照json转义规则转义webrtc answer sdp
static
char
*
escape_string
(
const
char
*
ptr
){
char
*
escaped
=
malloc
(
2
*
strlen
(
ptr
));
char
*
ptr_escaped
=
escaped
;
while
(
1
)
{
switch
(
*
ptr
)
{
case
'\r'
:
{
*
(
ptr_escaped
++
)
=
'\\'
;
*
(
ptr_escaped
++
)
=
'r'
;
break
;
}
case
'\n'
:
{
*
(
ptr_escaped
++
)
=
'\\'
;
*
(
ptr_escaped
++
)
=
'n'
;
break
;
}
case
'\t'
:
{
*
(
ptr_escaped
++
)
=
'\\'
;
*
(
ptr_escaped
++
)
=
't'
;
break
;
}
default
:
{
*
(
ptr_escaped
++
)
=
*
ptr
;
if
(
!*
ptr
)
{
return
escaped
;
}
break
;
}
}
++
ptr
;
}
}
static
void
on_mk_webrtc_get_answer_sdp_func
(
void
*
user_data
,
const
char
*
answer
,
const
char
*
err
)
{
const
char
*
response_header
[]
=
{
"Content-Type"
,
"application/json"
,
"Access-Control-Allow-Origin"
,
"*"
,
NULL
};
if
(
answer
)
{
answer
=
escape_string
(
answer
);
}
size_t
len
=
answer
?
2
*
strlen
(
answer
)
:
1024
;
char
*
response_content
=
(
char
*
)
malloc
(
len
);
if
(
answer
)
{
snprintf
(
response_content
,
len
,
"{"
"
\"
sdp
\"
:
\"
%s
\"
,"
"
\"
type
\"
:
\"
answer
\"
,"
"
\"
code
\"
:0"
"}"
,
answer
);
}
else
{
snprintf
(
response_content
,
len
,
"{"
"
\"
msg
\"
:
\"
%s
\"
,"
"
\"
code
\"
:-1"
"}"
,
err
);
}
mk_http_response_invoker_do_string
(
user_data
,
200
,
response_header
,
response_content
);
mk_http_response_invoker_clone_release
(
user_data
);
free
(
response_content
);
if
(
answer
)
{
free
((
void
*
)
answer
);
}
}
/**
* 收到http api请求广播(包括GET/POST)
* @param parser http请求内容对象
* @param invoker 执行该invoker返回http回复
* @param consumed 置1则说明我们要处理该事件
* @param sender http客户端相关信息
*/
//测试url : http://127.0.0.1/api/test
void
API_CALL
on_mk_http_request
(
const
mk_parser
parser
,
const
mk_http_response_invoker
invoker
,
int
*
consumed
,
const
mk_sock_info
sender
)
{
const
char
*
url
=
mk_parser_get_url
(
parser
);
*
consumed
=
1
;
if
(
strcmp
(
url
,
"/index/api/webrtc"
)
==
0
)
{
//拦截api: /index/api/webrtc
char
rtc_url
[
1024
];
snprintf
(
rtc_url
,
sizeof
(
rtc_url
),
"rtc://%s/%s/%s?%s"
,
mk_parser_get_header
(
parser
,
"Host"
),
mk_parser_get_url_param
(
parser
,
"app"
),
mk_parser_get_url_param
(
parser
,
"stream"
),
mk_parser_get_url_params
(
parser
));
mk_webrtc_get_answer_sdp
(
mk_http_response_invoker_clone
(
invoker
),
on_mk_webrtc_get_answer_sdp_func
,
mk_parser_get_url_param
(
parser
,
"type"
),
mk_parser_get_content
(
parser
,
NULL
),
rtc_url
);
}
else
{
*
consumed
=
0
;
return
;
}
}
int
main
(
int
argc
,
char
*
argv
[])
{
char
*
ini_path
=
mk_util_get_exe_dir
(
"config.ini"
);
mk_config
config
=
{
.
ini
=
NULL
,
.
ini
=
ini_path
,
.
ini_is_path
=
1
,
.
log_level
=
0
,
.
log_mask
=
LOG_CONSOLE
,
...
...
@@ -50,11 +149,29 @@ int main(int argc, char *argv[]) {
.
thread_num
=
0
};
mk_env_init
(
&
config
);
mk_free
(
ini_path
);
mk_http_server_start
(
80
,
0
);
mk_rtsp_server_start
(
554
,
0
);
mk_rtmp_server_start
(
1935
,
0
);
mk_rtc_server_start
(
atoi
(
mk_get_option
(
"rtc.port"
)));
signal
(
SIGINT
,
s_on_exit
);
// 设置退出信号
mk_events
events
=
{
.
on_mk_media_changed
=
NULL
,
.
on_mk_media_publish
=
NULL
,
.
on_mk_media_play
=
NULL
,
.
on_mk_media_not_found
=
NULL
,
.
on_mk_media_no_reader
=
NULL
,
.
on_mk_http_request
=
on_mk_http_request
,
.
on_mk_http_access
=
NULL
,
.
on_mk_http_before_access
=
NULL
,
.
on_mk_rtsp_get_realm
=
NULL
,
.
on_mk_rtsp_auth
=
NULL
,
.
on_mk_record_mp4
=
NULL
,
.
on_mk_shell_login
=
NULL
,
.
on_mk_flow_report
=
NULL
};
mk_events_listen
(
&
events
);
FILE
*
fp
=
fopen
(
argv
[
1
],
"rb"
);
if
(
!
fp
)
{
...
...
@@ -65,14 +182,15 @@ int main(int argc, char *argv[]) {
mk_media
media
=
mk_media_create
(
"__defaultVhost__"
,
"live"
,
"test"
,
0
,
0
,
0
);
//h264的codec
//mk_media_init_video(media, 0, 0, 0, 0, 2 * 104 * 1024);
codec_args
v_args
=
{
0
};
mk_track
v_track
=
mk_track_create
(
MKCodecH264
,
&
v_args
);
mk_media_init_track
(
media
,
v_track
);
codec_args
v_args
=
{
0
};
mk_track
v_track
=
mk_track_create
(
MKCodecH264
,
&
v_args
);
mk_media_init_track
(
media
,
v_track
);
mk_media_init_complete
(
media
);
mk_track_unref
(
v_track
);
//创建h264分帧器
mk_h264_splitter
splitter
=
mk_h264_splitter_create
(
on_h264_frame
,
media
);
mk_h264_splitter
splitter
=
mk_h264_splitter_create
(
on_h264_frame
,
media
,
0
);
signal
(
SIGINT
,
s_on_exit
);
// 设置退出信号
char
buf
[
1024
];
while
(
!
exit_flag
)
{
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论