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
071d0a9f
Commit
071d0a9f
authored
Sep 20, 2020
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
提炼MP4相关接口和代码
parent
2dd10461
隐藏空白字符变更
内嵌
并排
正在显示
9 个修改的文件
包含
180 行增加
和
62 行删除
+180
-62
src/Record/MP4.cpp
+27
-17
src/Record/MP4.h
+76
-14
src/Record/MP4Demuxer.cpp
+8
-6
src/Record/MP4Demuxer.h
+44
-8
src/Record/MP4Muxer.cpp
+5
-6
src/Record/MP4Muxer.h
+9
-4
src/Record/MP4Reader.cpp
+2
-1
src/Record/MP4Reader.h
+5
-3
src/Record/MP4Recorder.cpp
+4
-3
没有找到文件。
src/Record/MP4.cpp
查看文件 @
071d0a9f
...
...
@@ -18,6 +18,8 @@
using
namespace
toolkit
;
namespace
mediakit
{
/////////////////////////////////////////////////mp4_writer_t/////////////////////////////////////////////////
struct
mp4_writer_t
{
int
is_fmp4
;
union
{
...
...
@@ -102,28 +104,32 @@ int mp4_writer_init_segment(mp4_writer_t* mp4){
}
}
/////////////////////////////////////////////////MP4FileIO/////////////////////////////////////////////////
static
struct
mov_buffer_t
s_io
=
{
[](
void
*
ctx
,
void
*
data
,
uint64_t
bytes
)
{
MP4File
*
thiz
=
(
MP4File
*
)
ctx
;
MP4File
IO
*
thiz
=
(
MP4FileIO
*
)
ctx
;
return
thiz
->
onRead
(
data
,
bytes
);
},
[](
void
*
ctx
,
const
void
*
data
,
uint64_t
bytes
)
{
MP4File
*
thiz
=
(
MP4File
*
)
ctx
;
MP4File
IO
*
thiz
=
(
MP4FileIO
*
)
ctx
;
return
thiz
->
onWrite
(
data
,
bytes
);
},
[](
void
*
ctx
,
uint64_t
offset
)
{
MP4File
*
thiz
=
(
MP4File
*
)
ctx
;
MP4File
IO
*
thiz
=
(
MP4FileIO
*
)
ctx
;
return
thiz
->
onSeek
(
offset
);
},
[](
void
*
ctx
)
{
MP4File
*
thiz
=
(
MP4File
*
)
ctx
;
MP4File
IO
*
thiz
=
(
MP4FileIO
*
)
ctx
;
return
thiz
->
onTell
();
}
};
MP4File
::
Writer
MP4File
::
createWriter
(
int
flags
,
bool
is_fmp4
){
MP4File
IO
::
Writer
MP4FileIO
::
createWriter
(
int
flags
,
bool
is_fmp4
){
Writer
writer
;
writer
.
reset
(
mp4_writer_create
(
is_fmp4
,
&
s_io
,
this
,
flags
),[](
mp4_writer_t
*
ptr
){
Ptr
self
=
shared_from_this
();
//保存自己的强引用,防止提前释放
writer
.
reset
(
mp4_writer_create
(
is_fmp4
,
&
s_io
,
this
,
flags
),[
self
](
mp4_writer_t
*
ptr
){
if
(
ptr
){
mp4_writer_destroy
(
ptr
);
}
...
...
@@ -134,9 +140,11 @@ MP4File::Writer MP4File::createWriter(int flags, bool is_fmp4){
return
writer
;
}
MP4File
::
Reader
MP4File
::
createReader
(){
MP4File
IO
::
Reader
MP4FileIO
::
createReader
(){
Reader
reader
;
reader
.
reset
(
mov_reader_create
(
&
s_io
,
this
),[](
mov_reader_t
*
ptr
){
Ptr
self
=
shared_from_this
();
//保存自己的强引用,防止提前释放
reader
.
reset
(
mov_reader_create
(
&
s_io
,
this
),[
self
](
mov_reader_t
*
ptr
){
if
(
ptr
){
mov_reader_destroy
(
ptr
);
}
...
...
@@ -147,15 +155,17 @@ MP4File::Reader MP4File::createReader(){
return
reader
;
}
/////////////////////////////////////////////////////MP4FileDisk/////////////////////////////////////////////////////////
#if defined(_WIN32) || defined(_WIN64)
#define fseek64 _fseeki64
#define ftell64 _ftelli64
#define ftell64 _ftelli64
#else
#define fseek64 fseek
#define ftell64 ftell
#define fseek64 fseek
#define ftell64 ftell
#endif
void
MP4File
::
openFile
(
const
char
*
file
,
const
char
*
mode
)
{
void
MP4File
Disk
::
openFile
(
const
char
*
file
,
const
char
*
mode
)
{
//创建文件
auto
fp
=
File
::
create_file
(
file
,
mode
);
if
(
!
fp
){
...
...
@@ -183,26 +193,26 @@ void MP4File::openFile(const char *file,const char *mode) {
});
}
void
MP4File
::
closeFile
()
{
void
MP4File
Disk
::
closeFile
()
{
_file
=
nullptr
;
}
int
MP4File
::
onRead
(
void
*
data
,
uint64_t
bytes
)
{
int
MP4File
Disk
::
onRead
(
void
*
data
,
uint64_t
bytes
)
{
if
(
bytes
==
fread
(
data
,
1
,
bytes
,
_file
.
get
())){
return
0
;
}
return
0
!=
ferror
(
_file
.
get
())
?
ferror
(
_file
.
get
())
:
-
1
/*EOF*/
;
}
int
MP4File
::
onWrite
(
const
void
*
data
,
uint64_t
bytes
)
{
int
MP4File
Disk
::
onWrite
(
const
void
*
data
,
uint64_t
bytes
)
{
return
bytes
==
fwrite
(
data
,
1
,
bytes
,
_file
.
get
())
?
0
:
ferror
(
_file
.
get
());
}
int
MP4File
::
onSeek
(
uint64_t
offset
)
{
int
MP4File
Disk
::
onSeek
(
uint64_t
offset
)
{
return
fseek64
(
_file
.
get
(),
offset
,
SEEK_SET
);
}
uint64_t
MP4File
::
onTell
()
{
uint64_t
MP4File
Disk
::
onTell
()
{
return
ftell64
(
_file
.
get
());
}
...
...
src/Record/MP4.h
查看文件 @
071d0a9f
...
...
@@ -23,6 +23,7 @@
using
namespace
std
;
namespace
mediakit
{
//以下是fmp4/mov的通用接口,简单包装了ireader/media-server的接口
typedef
struct
mp4_writer_t
mp4_writer_t
;
mp4_writer_t
*
mp4_writer_create
(
int
is_fmp4
,
const
struct
mov_buffer_t
*
buffer
,
void
*
param
,
int
flags
);
void
mp4_writer_destroy
(
mp4_writer_t
*
mp4
);
...
...
@@ -34,23 +35,84 @@ int mp4_writer_write_l(mp4_writer_t* mp4, int track, const void* data, size_t by
int
mp4_writer_save_segment
(
mp4_writer_t
*
mp4
);
int
mp4_writer_init_segment
(
mp4_writer_t
*
mp4
);
class
MP4File
{
//mp4文件IO的抽象接口类
class
MP4FileIO
:
public
std
::
enable_shared_from_this
<
MP4FileIO
>
{
public
:
friend
struct
mov_buffer_t
;
typedef
std
::
shared_ptr
<
mp4_writer_t
>
Writer
;
typedef
std
::
shared_ptr
<
mov_reader_t
>
Reader
;
MP4File
()
=
default
;
virtual
~
MP4File
()
=
default
;
Writer
createWriter
(
int
flags
,
bool
is_fmp4
=
false
);
Reader
createReader
();
void
openFile
(
const
char
*
file
,
const
char
*
mode
);
using
Ptr
=
std
::
shared_ptr
<
MP4FileIO
>
;
using
Writer
=
std
::
shared_ptr
<
mp4_writer_t
>
;
using
Reader
=
std
::
shared_ptr
<
mov_reader_t
>
;
MP4FileIO
()
=
default
;
virtual
~
MP4FileIO
()
=
default
;
/**
* 创建mp4复用器
* @param flags 支持0、MOV_FLAG_FASTSTART、MOV_FLAG_SEGMENT
* @param is_fmp4 是否为fmp4还是普通mp4
* @return mp4复用器
*/
virtual
Writer
createWriter
(
int
flags
,
bool
is_fmp4
=
false
);
/**
* 创建mp4解复用器
* @return mp4解复用器
*/
virtual
Reader
createReader
();
/**
* 获取文件读写位置
*/
virtual
uint64_t
onTell
()
=
0
;
/**
* seek至文件某处
* @param offset 文件偏移量
* @return 是否成功(0成功)
*/
virtual
int
onSeek
(
uint64_t
offset
)
=
0
;
/**
* 从文件读取一定数据
* @param data 数据存放指针
* @param bytes 指针长度
* @return 是否成功(0成功)
*/
virtual
int
onRead
(
void
*
data
,
uint64_t
bytes
)
=
0
;
/**
* 写入文件一定数据
* @param data 数据指针
* @param bytes 数据长度
* @return 是否成功(0成功)
*/
virtual
int
onWrite
(
const
void
*
data
,
uint64_t
bytes
)
=
0
;
};
//磁盘MP4文件类
class
MP4FileDisk
:
public
MP4FileIO
{
public
:
using
Ptr
=
std
::
shared_ptr
<
MP4FileDisk
>
;
MP4FileDisk
()
=
default
;
~
MP4FileDisk
()
override
=
default
;
/**
* 打开磁盘文件
* @param file 文件路径
* @param mode fopen的方式
*/
void
openFile
(
const
char
*
file
,
const
char
*
mode
);
/**
* 关闭磁盘文件
*/
void
closeFile
();
int
onRead
(
void
*
data
,
uint64_t
bytes
);
int
onWrite
(
const
void
*
data
,
uint64_t
bytes
);
int
onSeek
(
uint64_t
offset
);
uint64_t
onTell
();
protected
:
uint64_t
onTell
()
override
;
int
onSeek
(
uint64_t
offset
)
override
;
int
onRead
(
void
*
data
,
uint64_t
bytes
)
override
;
int
onWrite
(
const
void
*
data
,
uint64_t
bytes
)
override
;
private
:
std
::
shared_ptr
<
FILE
>
_file
;
};
...
...
src/Record/MP4Demuxer.cpp
查看文件 @
071d0a9f
...
...
@@ -19,18 +19,20 @@
using
namespace
toolkit
;
namespace
mediakit
{
MP4Demuxer
::
MP4Demuxer
(
const
char
*
file
)
{
openFile
(
file
,
"rb+"
);
_mov_reader
=
createReader
();
getAllTracks
();
_duration_ms
=
mov_reader_getduration
(
_mov_reader
.
get
());
}
MP4Demuxer
::
MP4Demuxer
()
{}
MP4Demuxer
::~
MP4Demuxer
()
{
_mov_reader
=
nullptr
;
closeFile
();
}
void
MP4Demuxer
::
openMP4
(
const
string
&
file
){
openFile
(
file
.
data
(),
"rb+"
);
_mov_reader
=
createReader
();
getAllTracks
();
_duration_ms
=
mov_reader_getduration
(
_mov_reader
.
get
());
}
int
MP4Demuxer
::
getAllTracks
()
{
static
mov_reader_trackinfo_t
s_on_track
=
{
[](
void
*
param
,
uint32_t
track
,
uint8_t
object
,
int
width
,
int
height
,
const
void
*
extra
,
size_t
bytes
)
{
...
...
src/Record/MP4Demuxer.h
查看文件 @
071d0a9f
...
...
@@ -16,24 +16,60 @@
#include "Util/ResourcePool.h"
namespace
mediakit
{
class
MP4Demuxer
:
public
MP4File
,
public
TrackSource
{
class
MP4Demuxer
:
public
MP4File
Disk
,
public
TrackSource
{
public
:
typedef
std
::
shared_ptr
<
MP4Demuxer
>
Ptr
;
MP4Demuxer
(
const
char
*
file
);
/**
* 创建mp4解复用器
*/
MP4Demuxer
();
~
MP4Demuxer
()
override
;
/**
* 打开文件
* @param file mp4文件路径
*/
void
openMP4
(
const
string
&
file
);
/**
* 移动时间轴至某处
* @param stamp_ms 预期的时间轴位置,单位毫秒
* @return 时间轴位置
*/
int64_t
seekTo
(
int64_t
stamp_ms
);
/**
* 读取一帧数据
* @param keyFrame 是否为关键帧
* @param eof 是否文件读取完毕
* @return 帧数据,可能为空
*/
Frame
::
Ptr
readFrame
(
bool
&
keyFrame
,
bool
&
eof
);
vector
<
Track
::
Ptr
>
getTracks
(
bool
trackReady
)
const
override
;
/**
* 获取所有Track信息
* @param trackReady 是否要求track为就绪状态
* @return 所有Track
*/
vector
<
Track
::
Ptr
>
getTracks
(
bool
trackReady
)
const
override
;
/**
* 获取文件长度
* @return 文件长度,单位毫秒
*/
uint64_t
getDurationMS
()
const
;
private
:
int
getAllTracks
();
void
onVideoTrack
(
uint32_t
track_id
,
uint8_t
object
,
int
width
,
int
height
,
const
void
*
extra
,
size_t
bytes
);
void
onAudioTrack
(
uint32_t
track_id
,
uint8_t
object
,
int
channel_count
,
int
bit_per_sample
,
int
sample_rate
,
const
void
*
extra
,
size_t
bytes
);
Frame
::
Ptr
makeFrame
(
uint32_t
track_id
,
const
Buffer
::
Ptr
&
buf
,
int64_t
pts
,
int64_t
dts
);
void
onVideoTrack
(
uint32_t
track_id
,
uint8_t
object
,
int
width
,
int
height
,
const
void
*
extra
,
size_t
bytes
);
void
onAudioTrack
(
uint32_t
track_id
,
uint8_t
object
,
int
channel_count
,
int
bit_per_sample
,
int
sample_rate
,
const
void
*
extra
,
size_t
bytes
);
Frame
::
Ptr
makeFrame
(
uint32_t
track_id
,
const
Buffer
::
Ptr
&
buf
,
int64_t
pts
,
int64_t
dts
);
private
:
MP4File
::
Reader
_mov_reader
;
Reader
_mov_reader
;
uint64_t
_duration_ms
=
0
;
map
<
int
,
Track
::
Ptr
>
_track_to_codec
;
map
<
int
,
Track
::
Ptr
>
_track_to_codec
;
ResourcePool
<
BufferRaw
>
_buffer_pool
;
};
...
...
src/Record/MP4Muxer.cpp
查看文件 @
071d0a9f
...
...
@@ -14,21 +14,20 @@
#include "Extension/H264.h"
namespace
mediakit
{
MP4Muxer
::
MP4Muxer
(
const
char
*
file
)
{
_file_name
=
file
;
openMP4
();
}
MP4Muxer
::
MP4Muxer
()
{}
MP4Muxer
::~
MP4Muxer
()
{
closeMP4
();
}
void
MP4Muxer
::
openMP4
(){
void
MP4Muxer
::
openMP4
(
const
string
&
file
){
_file_name
=
file
;
closeMP4
();
openFile
(
_file_name
.
data
(),
"wb+"
);
GET_CONFIG
(
bool
,
mp4FastStart
,
Record
::
kFastStart
);
_mov_writter
=
createWriter
(
mp4FastStart
?
MOV_FLAG_FASTSTART
:
0
,
false
);
}
void
MP4Muxer
::
closeMP4
(){
_mov_writter
=
nullptr
;
closeFile
();
...
...
@@ -38,7 +37,7 @@ void MP4Muxer::resetTracks() {
_codec_to_trackid
.
clear
();
_started
=
false
;
_have_video
=
false
;
openMP4
();
openMP4
(
_file_name
);
}
void
MP4Muxer
::
inputFrame
(
const
Frame
::
Ptr
&
frame
)
{
...
...
src/Record/MP4Muxer.h
查看文件 @
071d0a9f
...
...
@@ -23,11 +23,11 @@
namespace
mediakit
{
class
MP4Muxer
:
public
MediaSinkInterface
,
public
MP4File
{
class
MP4Muxer
:
public
MediaSinkInterface
,
public
MP4File
Disk
{
public
:
typedef
std
::
shared_ptr
<
MP4Muxer
>
Ptr
;
MP4Muxer
(
const
char
*
file
);
MP4Muxer
();
~
MP4Muxer
()
override
;
/**
...
...
@@ -45,12 +45,17 @@ public:
void
resetTracks
()
override
;
/**
* 打开mp4
* @param file 文件完整路径
*/
void
openMP4
(
const
string
&
file
);
/**
* 手动关闭文件(对象析构时会自动关闭)
*/
void
closeMP4
();
private
:
void
openMP4
();
void
stampSync
();
private
:
...
...
@@ -62,8 +67,8 @@ private:
List
<
Frame
::
Ptr
>
_frameCached
;
bool
_started
=
false
;
bool
_have_video
=
false
;
MP4File
::
Writer
_mov_writter
;
string
_file_name
;
Writer
_mov_writter
;
};
}
//namespace mediakit
...
...
src/Record/MP4Reader.cpp
查看文件 @
071d0a9f
...
...
@@ -29,7 +29,8 @@ MP4Reader::MP4Reader(const string &strVhost,const string &strApp, const string &
strFileName
=
File
::
absolutePath
(
strFileName
,
recordPath
);
}
_demuxer
=
std
::
make_shared
<
MP4Demuxer
>
(
strFileName
.
data
());
_demuxer
=
std
::
make_shared
<
MP4Demuxer
>
();
_demuxer
->
openMP4
(
strFileName
);
_mediaMuxer
.
reset
(
new
MultiMediaSourceMuxer
(
strVhost
,
strApp
,
strId
,
_demuxer
->
getDurationMS
()
/
1000.0
,
true
,
true
,
false
,
false
));
auto
tracks
=
_demuxer
->
getTracks
(
false
);
if
(
tracks
.
empty
()){
...
...
src/Record/MP4Reader.h
查看文件 @
071d0a9f
...
...
@@ -35,6 +35,7 @@ public:
* 意思是在文件流化结束之前或中断之前,MP4Reader对象是不会被销毁的(不管有没有被外部对象持有)
*/
void
startReadMP4
();
private
:
//MediaSourceEvent override
bool
seekTo
(
MediaSource
&
sender
,
uint32_t
ui32Stamp
)
override
;
...
...
@@ -45,15 +46,16 @@ private:
uint32_t
getCurrentStamp
();
void
setCurrentStamp
(
uint32_t
ui32Stamp
);
bool
seekTo
(
uint32_t
ui32Stamp
);
private
:
recursive_mutex
_mtx
;
MultiMediaSourceMuxer
::
Ptr
_mediaMuxer
;
bool
_have_video
=
false
;
uint32_t
_seek_to
;
recursive_mutex
_mtx
;
Ticker
_seek_ticker
;
Timer
::
Ptr
_timer
;
EventPoller
::
Ptr
_poller
;
MP4Demuxer
::
Ptr
_demuxer
;
bool
_have_video
=
false
;
MultiMediaSourceMuxer
::
Ptr
_mediaMuxer
;
};
}
/* namespace mediakit */
...
...
src/Record/MP4Recorder.cpp
查看文件 @
071d0a9f
...
...
@@ -53,15 +53,16 @@ void MP4Recorder::createFile() {
+
strTime
+
".mp4"
;
try
{
_muxer
=
std
::
make_shared
<
MP4Muxer
>
(
strFileTmp
.
data
());
for
(
auto
&
track
:
_tracks
){
_muxer
=
std
::
make_shared
<
MP4Muxer
>
();
_muxer
->
openMP4
(
strFileTmp
);
for
(
auto
&
track
:
_tracks
)
{
//添加track
_muxer
->
addTrack
(
track
);
}
_strFileTmp
=
strFileTmp
;
_strFile
=
strFile
;
_createFileTicker
.
resetTime
();
}
catch
(
std
::
exception
&
ex
)
{
}
catch
(
std
::
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论