Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
小白菜888
Ffmpeg
提交
609d8646
F
Ffmpeg
项目概览
小白菜888
/
Ffmpeg
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
Ffmpeg
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
609d8646
编写于
11月 08, 2009
作者:
B
Baptiste Coudurier
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
move code to avoid forward declaration
Originally committed as revision 20475 to
svn://svn.ffmpeg.org/ffmpeg/trunk
上级
b3f9f7a3
变更
1
隐藏空白更改
内联
并排
Showing
1 changed file
with
238 addition
and
240 deletion
+238
-240
libavformat/mpegts.c
libavformat/mpegts.c
+238
-240
未找到文件。
libavformat/mpegts.c
浏览文件 @
609d8646
...
...
@@ -42,8 +42,6 @@
typedef
struct
PESContext
PESContext
;
static
PESContext
*
add_pes_stream
(
MpegTSContext
*
ts
,
int
pid
,
int
pcr_pid
);
enum
MpegTSFilterType
{
MPEGTS_PES
,
MPEGTS_SECTION
,
...
...
@@ -604,6 +602,244 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
return
0
;
}
static
int64_t
get_pts
(
const
uint8_t
*
p
)
{
int64_t
pts
=
(
int64_t
)((
p
[
0
]
>>
1
)
&
0x07
)
<<
30
;
pts
|=
(
AV_RB16
(
p
+
1
)
>>
1
)
<<
15
;
pts
|=
AV_RB16
(
p
+
3
)
>>
1
;
return
pts
;
}
static
void
new_pes_packet
(
PESContext
*
pes
,
AVPacket
*
pkt
)
{
av_init_packet
(
pkt
);
pkt
->
destruct
=
av_destruct_packet
;
pkt
->
data
=
pes
->
buffer
;
pkt
->
size
=
pes
->
data_index
;
memset
(
pkt
->
data
+
pkt
->
size
,
0
,
FF_INPUT_BUFFER_PADDING_SIZE
);
// Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID
if
(
pes
->
sub_st
&&
pes
->
stream_type
==
0x83
&&
pes
->
extended_stream_id
==
0x76
)
pkt
->
stream_index
=
pes
->
sub_st
->
index
;
else
pkt
->
stream_index
=
pes
->
st
->
index
;
pkt
->
pts
=
pes
->
pts
;
pkt
->
dts
=
pes
->
dts
;
/* store position of first TS packet of this PES packet */
pkt
->
pos
=
pes
->
ts_packet_pos
;
/* reset pts values */
pes
->
pts
=
AV_NOPTS_VALUE
;
pes
->
dts
=
AV_NOPTS_VALUE
;
pes
->
buffer
=
NULL
;
pes
->
data_index
=
0
;
}
/* return non zero if a packet could be constructed */
static
int
mpegts_push_data
(
MpegTSFilter
*
filter
,
const
uint8_t
*
buf
,
int
buf_size
,
int
is_start
,
int64_t
pos
)
{
PESContext
*
pes
=
filter
->
u
.
pes_filter
.
opaque
;
MpegTSContext
*
ts
=
pes
->
ts
;
const
uint8_t
*
p
;
int
len
,
code
;
if
(
!
ts
->
pkt
)
return
0
;
if
(
is_start
)
{
if
(
pes
->
state
==
MPEGTS_PAYLOAD
&&
pes
->
data_index
>
0
)
{
new_pes_packet
(
pes
,
ts
->
pkt
);
ts
->
stop_parse
=
1
;
}
pes
->
state
=
MPEGTS_HEADER
;
pes
->
data_index
=
0
;
pes
->
ts_packet_pos
=
pos
;
}
p
=
buf
;
while
(
buf_size
>
0
)
{
switch
(
pes
->
state
)
{
case
MPEGTS_HEADER
:
len
=
PES_START_SIZE
-
pes
->
data_index
;
if
(
len
>
buf_size
)
len
=
buf_size
;
memcpy
(
pes
->
header
+
pes
->
data_index
,
p
,
len
);
pes
->
data_index
+=
len
;
p
+=
len
;
buf_size
-=
len
;
if
(
pes
->
data_index
==
PES_START_SIZE
)
{
/* we got all the PES or section header. We can now
decide */
#if 0
av_hex_dump_log(pes->stream, AV_LOG_DEBUG, pes->header, pes->data_index);
#endif
if
(
pes
->
header
[
0
]
==
0x00
&&
pes
->
header
[
1
]
==
0x00
&&
pes
->
header
[
2
]
==
0x01
)
{
/* it must be an mpeg2 PES stream */
code
=
pes
->
header
[
3
]
|
0x100
;
dprintf
(
pes
->
stream
,
"pid=%x pes_code=%#x
\n
"
,
pes
->
pid
,
code
);
if
((
!
pes
->
st
&&
pes
->
stream
->
nb_streams
==
MAX_STREAMS
)
||
(
pes
->
st
&&
pes
->
st
->
discard
==
AVDISCARD_ALL
)
||
code
==
0x1be
)
/* padding_stream */
goto
skip
;
/* stream not present in PMT */
if
(
!
pes
->
st
)
{
pes
->
st
=
av_new_stream
(
ts
->
stream
,
pes
->
pid
);
if
(
!
pes
->
st
)
return
AVERROR
(
ENOMEM
);
mpegts_set_stream_info
(
pes
->
st
,
pes
,
0
,
0
);
}
pes
->
total_size
=
AV_RB16
(
pes
->
header
+
4
);
/* NOTE: a zero total size means the PES size is
unbounded */
if
(
!
pes
->
total_size
)
pes
->
total_size
=
MAX_PES_PAYLOAD
;
/* allocate pes buffer */
pes
->
buffer
=
av_malloc
(
pes
->
total_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
if
(
!
pes
->
buffer
)
return
AVERROR
(
ENOMEM
);
if
(
code
!=
0x1bc
&&
code
!=
0x1bf
&&
/* program_stream_map, private_stream_2 */
code
!=
0x1f0
&&
code
!=
0x1f1
&&
/* ECM, EMM */
code
!=
0x1ff
&&
code
!=
0x1f2
&&
/* program_stream_directory, DSMCC_stream */
code
!=
0x1f8
)
{
/* ITU-T Rec. H.222.1 type E stream */
pes
->
state
=
MPEGTS_PESHEADER
;
if
(
pes
->
st
->
codec
->
codec_id
==
CODEC_ID_NONE
)
{
dprintf
(
pes
->
stream
,
"pid=%x stream_type=%x probing
\n
"
,
pes
->
pid
,
pes
->
stream_type
);
pes
->
st
->
codec
->
codec_id
=
CODEC_ID_PROBE
;
}
}
else
{
pes
->
state
=
MPEGTS_PAYLOAD
;
pes
->
data_index
=
0
;
}
}
else
{
/* otherwise, it should be a table */
/* skip packet */
skip:
pes
->
state
=
MPEGTS_SKIP
;
continue
;
}
}
break
;
/**********************************************/
/* PES packing parsing */
case
MPEGTS_PESHEADER
:
len
=
PES_HEADER_SIZE
-
pes
->
data_index
;
if
(
len
<
0
)
return
-
1
;
if
(
len
>
buf_size
)
len
=
buf_size
;
memcpy
(
pes
->
header
+
pes
->
data_index
,
p
,
len
);
pes
->
data_index
+=
len
;
p
+=
len
;
buf_size
-=
len
;
if
(
pes
->
data_index
==
PES_HEADER_SIZE
)
{
pes
->
pes_header_size
=
pes
->
header
[
8
]
+
9
;
pes
->
state
=
MPEGTS_PESHEADER_FILL
;
}
break
;
case
MPEGTS_PESHEADER_FILL
:
len
=
pes
->
pes_header_size
-
pes
->
data_index
;
if
(
len
<
0
)
return
-
1
;
if
(
len
>
buf_size
)
len
=
buf_size
;
memcpy
(
pes
->
header
+
pes
->
data_index
,
p
,
len
);
pes
->
data_index
+=
len
;
p
+=
len
;
buf_size
-=
len
;
if
(
pes
->
data_index
==
pes
->
pes_header_size
)
{
const
uint8_t
*
r
;
unsigned
int
flags
,
pes_ext
,
skip
;
flags
=
pes
->
header
[
7
];
r
=
pes
->
header
+
9
;
pes
->
pts
=
AV_NOPTS_VALUE
;
pes
->
dts
=
AV_NOPTS_VALUE
;
if
((
flags
&
0xc0
)
==
0x80
)
{
pes
->
dts
=
pes
->
pts
=
get_pts
(
r
);
r
+=
5
;
}
else
if
((
flags
&
0xc0
)
==
0xc0
)
{
pes
->
pts
=
get_pts
(
r
);
r
+=
5
;
pes
->
dts
=
get_pts
(
r
);
r
+=
5
;
}
pes
->
extended_stream_id
=
-
1
;
if
(
flags
&
0x01
)
{
/* PES extension */
pes_ext
=
*
r
++
;
/* Skip PES private data, program packet sequence counter and P-STD buffer */
skip
=
(
pes_ext
>>
4
)
&
0xb
;
skip
+=
skip
&
0x9
;
r
+=
skip
;
if
((
pes_ext
&
0x41
)
==
0x01
&&
(
r
+
2
)
<=
(
pes
->
header
+
pes
->
pes_header_size
))
{
/* PES extension 2 */
if
((
r
[
0
]
&
0x7f
)
>
0
&&
(
r
[
1
]
&
0x80
)
==
0
)
pes
->
extended_stream_id
=
r
[
1
];
}
}
/* we got the full header. We parse it and get the payload */
pes
->
state
=
MPEGTS_PAYLOAD
;
pes
->
data_index
=
0
;
}
break
;
case
MPEGTS_PAYLOAD
:
if
(
buf_size
>
0
&&
pes
->
buffer
)
{
if
(
pes
->
data_index
+
buf_size
>
pes
->
total_size
)
{
new_pes_packet
(
pes
,
ts
->
pkt
);
pes
->
total_size
=
MAX_PES_PAYLOAD
;
pes
->
buffer
=
av_malloc
(
pes
->
total_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
if
(
!
pes
->
buffer
)
return
AVERROR
(
ENOMEM
);
ts
->
stop_parse
=
1
;
}
memcpy
(
pes
->
buffer
+
pes
->
data_index
,
p
,
buf_size
);
pes
->
data_index
+=
buf_size
;
}
buf_size
=
0
;
break
;
case
MPEGTS_SKIP
:
buf_size
=
0
;
break
;
}
}
return
0
;
}
static
PESContext
*
add_pes_stream
(
MpegTSContext
*
ts
,
int
pid
,
int
pcr_pid
)
{
MpegTSFilter
*
tss
;
PESContext
*
pes
;
/* if no pid found, then add a pid context */
pes
=
av_mallocz
(
sizeof
(
PESContext
));
if
(
!
pes
)
return
0
;
pes
->
ts
=
ts
;
pes
->
stream
=
ts
->
stream
;
pes
->
pid
=
pid
;
pes
->
pcr_pid
=
pcr_pid
;
pes
->
state
=
MPEGTS_SKIP
;
pes
->
pts
=
AV_NOPTS_VALUE
;
pes
->
dts
=
AV_NOPTS_VALUE
;
tss
=
mpegts_open_pes_filter
(
ts
,
pid
,
mpegts_push_data
,
pes
);
if
(
!
tss
)
{
av_free
(
pes
);
return
0
;
}
return
pes
;
}
static
void
pmt_cb
(
MpegTSFilter
*
filter
,
const
uint8_t
*
section
,
int
section_len
)
{
MpegTSContext
*
ts
=
filter
->
u
.
section_filter
.
opaque
;
...
...
@@ -888,244 +1124,6 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
}
}
static
int64_t
get_pts
(
const
uint8_t
*
p
)
{
int64_t
pts
=
(
int64_t
)((
p
[
0
]
>>
1
)
&
0x07
)
<<
30
;
pts
|=
(
AV_RB16
(
p
+
1
)
>>
1
)
<<
15
;
pts
|=
AV_RB16
(
p
+
3
)
>>
1
;
return
pts
;
}
static
void
new_pes_packet
(
PESContext
*
pes
,
AVPacket
*
pkt
)
{
av_init_packet
(
pkt
);
pkt
->
destruct
=
av_destruct_packet
;
pkt
->
data
=
pes
->
buffer
;
pkt
->
size
=
pes
->
data_index
;
memset
(
pkt
->
data
+
pkt
->
size
,
0
,
FF_INPUT_BUFFER_PADDING_SIZE
);
// Separate out the AC3 substream from an HDMV combined TrueHD/AC3 PID
if
(
pes
->
sub_st
&&
pes
->
stream_type
==
0x83
&&
pes
->
extended_stream_id
==
0x76
)
pkt
->
stream_index
=
pes
->
sub_st
->
index
;
else
pkt
->
stream_index
=
pes
->
st
->
index
;
pkt
->
pts
=
pes
->
pts
;
pkt
->
dts
=
pes
->
dts
;
/* store position of first TS packet of this PES packet */
pkt
->
pos
=
pes
->
ts_packet_pos
;
/* reset pts values */
pes
->
pts
=
AV_NOPTS_VALUE
;
pes
->
dts
=
AV_NOPTS_VALUE
;
pes
->
buffer
=
NULL
;
pes
->
data_index
=
0
;
}
/* return non zero if a packet could be constructed */
static
int
mpegts_push_data
(
MpegTSFilter
*
filter
,
const
uint8_t
*
buf
,
int
buf_size
,
int
is_start
,
int64_t
pos
)
{
PESContext
*
pes
=
filter
->
u
.
pes_filter
.
opaque
;
MpegTSContext
*
ts
=
pes
->
ts
;
const
uint8_t
*
p
;
int
len
,
code
;
if
(
!
ts
->
pkt
)
return
0
;
if
(
is_start
)
{
if
(
pes
->
state
==
MPEGTS_PAYLOAD
&&
pes
->
data_index
>
0
)
{
new_pes_packet
(
pes
,
ts
->
pkt
);
ts
->
stop_parse
=
1
;
}
pes
->
state
=
MPEGTS_HEADER
;
pes
->
data_index
=
0
;
pes
->
ts_packet_pos
=
pos
;
}
p
=
buf
;
while
(
buf_size
>
0
)
{
switch
(
pes
->
state
)
{
case
MPEGTS_HEADER
:
len
=
PES_START_SIZE
-
pes
->
data_index
;
if
(
len
>
buf_size
)
len
=
buf_size
;
memcpy
(
pes
->
header
+
pes
->
data_index
,
p
,
len
);
pes
->
data_index
+=
len
;
p
+=
len
;
buf_size
-=
len
;
if
(
pes
->
data_index
==
PES_START_SIZE
)
{
/* we got all the PES or section header. We can now
decide */
#if 0
av_hex_dump_log(pes->stream, AV_LOG_DEBUG, pes->header, pes->data_index);
#endif
if
(
pes
->
header
[
0
]
==
0x00
&&
pes
->
header
[
1
]
==
0x00
&&
pes
->
header
[
2
]
==
0x01
)
{
/* it must be an mpeg2 PES stream */
code
=
pes
->
header
[
3
]
|
0x100
;
dprintf
(
pes
->
stream
,
"pid=%x pes_code=%#x
\n
"
,
pes
->
pid
,
code
);
if
((
!
pes
->
st
&&
pes
->
stream
->
nb_streams
==
MAX_STREAMS
)
||
(
pes
->
st
&&
pes
->
st
->
discard
==
AVDISCARD_ALL
)
||
code
==
0x1be
)
/* padding_stream */
goto
skip
;
/* stream not present in PMT */
if
(
!
pes
->
st
)
{
pes
->
st
=
av_new_stream
(
ts
->
stream
,
pes
->
pid
);
if
(
!
pes
->
st
)
return
AVERROR
(
ENOMEM
);
mpegts_set_stream_info
(
pes
->
st
,
pes
,
0
,
0
);
}
pes
->
total_size
=
AV_RB16
(
pes
->
header
+
4
);
/* NOTE: a zero total size means the PES size is
unbounded */
if
(
!
pes
->
total_size
)
pes
->
total_size
=
MAX_PES_PAYLOAD
;
/* allocate pes buffer */
pes
->
buffer
=
av_malloc
(
pes
->
total_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
if
(
!
pes
->
buffer
)
return
AVERROR
(
ENOMEM
);
if
(
code
!=
0x1bc
&&
code
!=
0x1bf
&&
/* program_stream_map, private_stream_2 */
code
!=
0x1f0
&&
code
!=
0x1f1
&&
/* ECM, EMM */
code
!=
0x1ff
&&
code
!=
0x1f2
&&
/* program_stream_directory, DSMCC_stream */
code
!=
0x1f8
)
{
/* ITU-T Rec. H.222.1 type E stream */
pes
->
state
=
MPEGTS_PESHEADER
;
if
(
pes
->
st
->
codec
->
codec_id
==
CODEC_ID_NONE
)
{
dprintf
(
pes
->
stream
,
"pid=%x stream_type=%x probing
\n
"
,
pes
->
pid
,
pes
->
stream_type
);
pes
->
st
->
codec
->
codec_id
=
CODEC_ID_PROBE
;
}
}
else
{
pes
->
state
=
MPEGTS_PAYLOAD
;
pes
->
data_index
=
0
;
}
}
else
{
/* otherwise, it should be a table */
/* skip packet */
skip:
pes
->
state
=
MPEGTS_SKIP
;
continue
;
}
}
break
;
/**********************************************/
/* PES packing parsing */
case
MPEGTS_PESHEADER
:
len
=
PES_HEADER_SIZE
-
pes
->
data_index
;
if
(
len
<
0
)
return
-
1
;
if
(
len
>
buf_size
)
len
=
buf_size
;
memcpy
(
pes
->
header
+
pes
->
data_index
,
p
,
len
);
pes
->
data_index
+=
len
;
p
+=
len
;
buf_size
-=
len
;
if
(
pes
->
data_index
==
PES_HEADER_SIZE
)
{
pes
->
pes_header_size
=
pes
->
header
[
8
]
+
9
;
pes
->
state
=
MPEGTS_PESHEADER_FILL
;
}
break
;
case
MPEGTS_PESHEADER_FILL
:
len
=
pes
->
pes_header_size
-
pes
->
data_index
;
if
(
len
<
0
)
return
-
1
;
if
(
len
>
buf_size
)
len
=
buf_size
;
memcpy
(
pes
->
header
+
pes
->
data_index
,
p
,
len
);
pes
->
data_index
+=
len
;
p
+=
len
;
buf_size
-=
len
;
if
(
pes
->
data_index
==
pes
->
pes_header_size
)
{
const
uint8_t
*
r
;
unsigned
int
flags
,
pes_ext
,
skip
;
flags
=
pes
->
header
[
7
];
r
=
pes
->
header
+
9
;
pes
->
pts
=
AV_NOPTS_VALUE
;
pes
->
dts
=
AV_NOPTS_VALUE
;
if
((
flags
&
0xc0
)
==
0x80
)
{
pes
->
dts
=
pes
->
pts
=
get_pts
(
r
);
r
+=
5
;
}
else
if
((
flags
&
0xc0
)
==
0xc0
)
{
pes
->
pts
=
get_pts
(
r
);
r
+=
5
;
pes
->
dts
=
get_pts
(
r
);
r
+=
5
;
}
pes
->
extended_stream_id
=
-
1
;
if
(
flags
&
0x01
)
{
/* PES extension */
pes_ext
=
*
r
++
;
/* Skip PES private data, program packet sequence counter and P-STD buffer */
skip
=
(
pes_ext
>>
4
)
&
0xb
;
skip
+=
skip
&
0x9
;
r
+=
skip
;
if
((
pes_ext
&
0x41
)
==
0x01
&&
(
r
+
2
)
<=
(
pes
->
header
+
pes
->
pes_header_size
))
{
/* PES extension 2 */
if
((
r
[
0
]
&
0x7f
)
>
0
&&
(
r
[
1
]
&
0x80
)
==
0
)
pes
->
extended_stream_id
=
r
[
1
];
}
}
/* we got the full header. We parse it and get the payload */
pes
->
state
=
MPEGTS_PAYLOAD
;
pes
->
data_index
=
0
;
}
break
;
case
MPEGTS_PAYLOAD
:
if
(
buf_size
>
0
&&
pes
->
buffer
)
{
if
(
pes
->
data_index
+
buf_size
>
pes
->
total_size
)
{
new_pes_packet
(
pes
,
ts
->
pkt
);
pes
->
total_size
=
MAX_PES_PAYLOAD
;
pes
->
buffer
=
av_malloc
(
pes
->
total_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
if
(
!
pes
->
buffer
)
return
AVERROR
(
ENOMEM
);
ts
->
stop_parse
=
1
;
}
memcpy
(
pes
->
buffer
+
pes
->
data_index
,
p
,
buf_size
);
pes
->
data_index
+=
buf_size
;
}
buf_size
=
0
;
break
;
case
MPEGTS_SKIP
:
buf_size
=
0
;
break
;
}
}
return
0
;
}
static
PESContext
*
add_pes_stream
(
MpegTSContext
*
ts
,
int
pid
,
int
pcr_pid
)
{
MpegTSFilter
*
tss
;
PESContext
*
pes
;
/* if no pid found, then add a pid context */
pes
=
av_mallocz
(
sizeof
(
PESContext
));
if
(
!
pes
)
return
0
;
pes
->
ts
=
ts
;
pes
->
stream
=
ts
->
stream
;
pes
->
pid
=
pid
;
pes
->
pcr_pid
=
pcr_pid
;
pes
->
state
=
MPEGTS_SKIP
;
pes
->
pts
=
AV_NOPTS_VALUE
;
pes
->
dts
=
AV_NOPTS_VALUE
;
tss
=
mpegts_open_pes_filter
(
ts
,
pid
,
mpegts_push_data
,
pes
);
if
(
!
tss
)
{
av_free
(
pes
);
return
0
;
}
return
pes
;
}
/* handle one TS packet */
static
int
handle_packet
(
MpegTSContext
*
ts
,
const
uint8_t
*
packet
)
{
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录