Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
Toggle navigation
F
ffmpeg.wasm-core
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
Linshizhi
ffmpeg.wasm-core
Commits
86ba2327
Commit
86ba2327
authored
Mar 17, 2014
by
Keiji Costantini
Committed by
Vittorio Giovara
Mar 18, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
mpegts: K&R formatting cosmetics
Signed-off-by:
Vittorio Giovara
<
vittorio.giovara@gmail.com
>
parent
75177b2f
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
391 additions
and
329 deletions
+391
-329
mpegts.c
libavformat/mpegts.c
+391
-329
No files found.
libavformat/mpegts.c
View file @
86ba2327
...
...
@@ -37,18 +37,18 @@
#include "isom.h"
/* maximum size in which we look for synchronisation if
synchronisation is lost */
*
synchronisation is lost */
#define MAX_RESYNC_SIZE 65536
#define MAX_PES_PAYLOAD 200
*
1024
#define MAX_PES_PAYLOAD 200
*
1024
#define MAX_MP4_DESCR_COUNT 16
#define MOD_UNLIKELY(modulus, dividend, divisor, prev_dividend) \
do { \
#define MOD_UNLIKELY(modulus, dividend, divisor, prev_dividend)
\
do {
\
if ((prev_dividend) == 0 || (dividend) - (prev_dividend) != (divisor)) \
(modulus) = (dividend) % (divisor); \
(prev_dividend) = (dividend); \
(modulus) = (dividend) % (divisor);
\
(prev_dividend) = (dividend);
\
} while (0)
enum
MpegTSFilterType
{
...
...
@@ -58,23 +58,24 @@ enum MpegTSFilterType {
typedef
struct
MpegTSFilter
MpegTSFilter
;
typedef
int
PESCallback
(
MpegTSFilter
*
f
,
const
uint8_t
*
buf
,
int
len
,
int
is_start
,
int64_t
pos
);
typedef
int
PESCallback
(
MpegTSFilter
*
f
,
const
uint8_t
*
buf
,
int
len
,
int
is_start
,
int64_t
pos
);
typedef
struct
MpegTSPESFilter
{
PESCallback
*
pes_cb
;
void
*
opaque
;
}
MpegTSPESFilter
;
typedef
void
SectionCallback
(
MpegTSFilter
*
f
,
const
uint8_t
*
buf
,
int
len
);
typedef
void
SectionCallback
(
MpegTSFilter
*
f
,
const
uint8_t
*
buf
,
int
len
);
typedef
void
SetServiceCallback
(
void
*
opaque
,
int
ret
);
typedef
void
SetServiceCallback
(
void
*
opaque
,
int
ret
);
typedef
struct
MpegTSSectionFilter
{
int
section_index
;
int
section_h_size
;
uint8_t
*
section_buf
;
unsigned
int
check_crc
:
1
;
unsigned
int
end_of_section_reached
:
1
;
unsigned
int
check_crc
:
1
;
unsigned
int
end_of_section_reached
:
1
;
SectionCallback
*
section_cb
;
void
*
opaque
;
}
MpegTSSectionFilter
;
...
...
@@ -92,7 +93,7 @@ struct MpegTSFilter {
#define MAX_PIDS_PER_PROGRAM 64
struct
Program
{
unsigned
int
id
;
//program id/service id
unsigned
int
id
;
//
program id/service id
unsigned
int
nb_pids
;
unsigned
int
pids
[
MAX_PIDS_PER_PROGRAM
];
};
...
...
@@ -101,47 +102,49 @@ struct MpegTSContext {
const
AVClass
*
class
;
/* user data */
AVFormatContext
*
stream
;
/** raw packet size, including FEC if present
*/
/** raw packet size, including FEC if present */
int
raw_packet_size
;
int
pos47
;
/** position corresponding to pos47, or 0 if pos47 invalid */
int64_t
pos
;
/** if true, all pids are analyzed to find streams
*/
/** if true, all pids are analyzed to find streams */
int
auto_guess
;
/** compute exact PCR for each transport stream packet
*/
/** compute exact PCR for each transport stream packet */
int
mpeg2ts_compute_pcr
;
int64_t
cur_pcr
;
/**< used to estimate the exact PCR
*/
int
pcr_incr
;
/**< used to estimate the exact PCR
*/
int64_t
cur_pcr
;
/**< used to estimate the exact PCR */
int
pcr_incr
;
/**< used to estimate the exact PCR */
/* data needed to handle file based ts */
/** stop parsing loop
*/
/** stop parsing loop */
int
stop_parse
;
/** packet containing Audio/Video data
*/
/** packet containing Audio/Video data */
AVPacket
*
pkt
;
/** to detect seek
*/
/** to detect seek */
int64_t
last_pos
;
/******************************************/
/* private mpegts data */
/* scan context */
/** structure to keep track of Program->pids mapping
*/
/** structure to keep track of Program->pids mapping */
unsigned
int
nb_prg
;
struct
Program
*
prg
;
/** filters for various streams specified by PMT + for the PAT and PMT */
MpegTSFilter
*
pids
[
NB_PID_MAX
];
};
static
const
AVOption
options
[]
=
{
{
"compute_pcr"
,
"Compute exact PCR for each transport stream packet."
,
offsetof
(
MpegTSContext
,
mpeg2ts_compute_pcr
),
AV_OPT_TYPE_INT
,
{.
i64
=
0
},
0
,
1
,
AV_OPT_FLAG_DECODING_PARAM
},
{
"ts_packetsize"
,
"Output option carrying the raw packet size."
,
offsetof
(
MpegTSContext
,
raw_packet_size
),
AV_OPT_TYPE_INT
,
{.
i64
=
0
},
0
,
0
,
AV_OPT_FLAG_DECODING_PARAM
|
AV_OPT_FLAG_EXPORT
|
AV_OPT_FLAG_READONLY
},
{
"compute_pcr"
,
"Compute exact PCR for each transport stream packet."
,
offsetof
(
MpegTSContext
,
mpeg2ts_compute_pcr
),
AV_OPT_TYPE_INT
,
{
.
i64
=
0
},
0
,
1
,
AV_OPT_FLAG_DECODING_PARAM
},
{
"ts_packetsize"
,
"Output option carrying the raw packet size."
,
offsetof
(
MpegTSContext
,
raw_packet_size
),
AV_OPT_TYPE_INT
,
{
.
i64
=
0
},
0
,
0
,
AV_OPT_FLAG_DECODING_PARAM
|
AV_OPT_FLAG_EXPORT
|
AV_OPT_FLAG_READONLY
},
{
NULL
},
};
...
...
@@ -195,15 +198,15 @@ static void clear_program(MpegTSContext *ts, unsigned int programid)
{
int
i
;
for
(
i
=
0
;
i
<
ts
->
nb_prg
;
i
++
)
if
(
ts
->
prg
[
i
].
id
==
programid
)
for
(
i
=
0
;
i
<
ts
->
nb_prg
;
i
++
)
if
(
ts
->
prg
[
i
].
id
==
programid
)
ts
->
prg
[
i
].
nb_pids
=
0
;
}
static
void
clear_programs
(
MpegTSContext
*
ts
)
{
av_freep
(
&
ts
->
prg
);
ts
->
nb_prg
=
0
;
ts
->
nb_prg
=
0
;
}
static
void
add_pat_entry
(
MpegTSContext
*
ts
,
unsigned
int
programid
)
...
...
@@ -219,20 +222,21 @@ static void add_pat_entry(MpegTSContext *ts, unsigned int programid)
ts
->
nb_prg
++
;
}
static
void
add_pid_to_pmt
(
MpegTSContext
*
ts
,
unsigned
int
programid
,
unsigned
int
pid
)
static
void
add_pid_to_pmt
(
MpegTSContext
*
ts
,
unsigned
int
programid
,
unsigned
int
pid
)
{
int
i
;
struct
Program
*
p
=
NULL
;
for
(
i
=
0
;
i
<
ts
->
nb_prg
;
i
++
)
{
if
(
ts
->
prg
[
i
].
id
==
programid
)
{
for
(
i
=
0
;
i
<
ts
->
nb_prg
;
i
++
)
{
if
(
ts
->
prg
[
i
].
id
==
programid
)
{
p
=
&
ts
->
prg
[
i
];
break
;
}
}
if
(
!
p
)
if
(
!
p
)
return
;
if
(
p
->
nb_pids
>=
MAX_PIDS_PER_PROGRAM
)
if
(
p
->
nb_pids
>=
MAX_PIDS_PER_PROGRAM
)
return
;
p
->
pids
[
p
->
nb_pids
++
]
=
pid
;
}
...
...
@@ -252,24 +256,22 @@ static int discard_pid(MpegTSContext *ts, unsigned int pid)
struct
Program
*
p
;
/* If none of the programs have .discard=AVDISCARD_ALL then there's
* no way we have to discard this packet
*/
for
(
k
=
0
;
k
<
ts
->
stream
->
nb_programs
;
k
++
)
{
* no way we have to discard this packet */
for
(
k
=
0
;
k
<
ts
->
stream
->
nb_programs
;
k
++
)
if
(
ts
->
stream
->
programs
[
k
]
->
discard
==
AVDISCARD_ALL
)
break
;
}
if
(
k
==
ts
->
stream
->
nb_programs
)
return
0
;
for
(
i
=
0
;
i
<
ts
->
nb_prg
;
i
++
)
{
for
(
i
=
0
;
i
<
ts
->
nb_prg
;
i
++
)
{
p
=
&
ts
->
prg
[
i
];
for
(
j
=
0
;
j
<
p
->
nb_pids
;
j
++
)
{
if
(
p
->
pids
[
j
]
!=
pid
)
for
(
j
=
0
;
j
<
p
->
nb_pids
;
j
++
)
{
if
(
p
->
pids
[
j
]
!=
pid
)
continue
;
//is program with id p->id set to be discarded?
for
(
k
=
0
;
k
<
ts
->
stream
->
nb_programs
;
k
++
)
{
if
(
ts
->
stream
->
programs
[
k
]
->
id
==
p
->
id
)
{
if
(
ts
->
stream
->
programs
[
k
]
->
discard
==
AVDISCARD_ALL
)
//
is program with id p->id set to be discarded?
for
(
k
=
0
;
k
<
ts
->
stream
->
nb_programs
;
k
++
)
{
if
(
ts
->
stream
->
programs
[
k
]
->
id
==
p
->
id
)
{
if
(
ts
->
stream
->
programs
[
k
]
->
discard
==
AVDISCARD_ALL
)
discarded
++
;
else
used
++
;
...
...
@@ -314,7 +316,8 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
tss
->
section_h_size
=
len
;
}
if
(
tss
->
section_h_size
!=
-
1
&&
tss
->
section_index
>=
tss
->
section_h_size
)
{
if
(
tss
->
section_h_size
!=
-
1
&&
tss
->
section_index
>=
tss
->
section_h_size
)
{
tss
->
end_of_section_reached
=
1
;
if
(
!
tss
->
check_crc
||
av_crc
(
av_crc_get_table
(
AV_CRC_32_IEEE
),
-
1
,
...
...
@@ -323,10 +326,11 @@ static void write_section_data(AVFormatContext *s, MpegTSFilter *tss1,
}
}
static
MpegTSFilter
*
mpegts_open_section_filter
(
MpegTSContext
*
ts
,
unsigned
int
pid
,
SectionCallback
*
section_cb
,
void
*
opaque
,
int
check_crc
)
static
MpegTSFilter
*
mpegts_open_section_filter
(
MpegTSContext
*
ts
,
unsigned
int
pid
,
SectionCallback
*
section_cb
,
void
*
opaque
,
int
check_crc
)
{
MpegTSFilter
*
filter
;
MpegTSSectionFilter
*
sec
;
...
...
@@ -339,15 +343,17 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int
if
(
!
filter
)
return
NULL
;
ts
->
pids
[
pid
]
=
filter
;
filter
->
type
=
MPEGTS_SECTION
;
filter
->
pid
=
pid
;
filter
->
es_id
=
-
1
;
filter
->
type
=
MPEGTS_SECTION
;
filter
->
pid
=
pid
;
filter
->
es_id
=
-
1
;
filter
->
last_cc
=
-
1
;
sec
=
&
filter
->
u
.
section_filter
;
sec
->
section_cb
=
section_cb
;
sec
->
opaque
=
opaque
;
sec
->
section_cb
=
section_cb
;
sec
->
opaque
=
opaque
;
sec
->
section_buf
=
av_malloc
(
MAX_SECTION_SIZE
);
sec
->
check_crc
=
check_crc
;
sec
->
check_crc
=
check_crc
;
if
(
!
sec
->
section_buf
)
{
av_free
(
filter
);
return
NULL
;
...
...
@@ -356,8 +362,8 @@ static MpegTSFilter *mpegts_open_section_filter(MpegTSContext *ts, unsigned int
}
static
MpegTSFilter
*
mpegts_open_pes_filter
(
MpegTSContext
*
ts
,
unsigned
int
pid
,
PESCallback
*
pes_cb
,
void
*
opaque
)
PESCallback
*
pes_cb
,
void
*
opaque
)
{
MpegTSFilter
*
filter
;
MpegTSPESFilter
*
pes
;
...
...
@@ -367,11 +373,13 @@ static MpegTSFilter *mpegts_open_pes_filter(MpegTSContext *ts, unsigned int pid,
filter
=
av_mallocz
(
sizeof
(
MpegTSFilter
));
if
(
!
filter
)
return
NULL
;
ts
->
pids
[
pid
]
=
filter
;
filter
->
type
=
MPEGTS_PES
;
filter
->
pid
=
pid
;
filter
->
es_id
=
-
1
;
filter
->
type
=
MPEGTS_PES
;
filter
->
pid
=
pid
;
filter
->
es_id
=
-
1
;
filter
->
last_cc
=
-
1
;
pes
=
&
filter
->
u
.
pes_filter
;
pes
->
pes_cb
=
pes_cb
;
pes
->
opaque
=
opaque
;
...
...
@@ -399,25 +407,28 @@ static void mpegts_close_filter(MpegTSContext *ts, MpegTSFilter *filter)
ts
->
pids
[
pid
]
=
NULL
;
}
static
int
analyze
(
const
uint8_t
*
buf
,
int
size
,
int
packet_size
,
int
*
index
){
static
int
analyze
(
const
uint8_t
*
buf
,
int
size
,
int
packet_size
,
int
*
index
)
{
int
stat
[
TS_MAX_PACKET_SIZE
];
int
i
;
int
x
=
0
;
int
best_score
=
0
;
int
x
=
0
;
int
best_score
=
0
;
memset
(
stat
,
0
,
packet_size
*
sizeof
(
int
));
memset
(
stat
,
0
,
packet_size
*
sizeof
(
int
));
for
(
x
=
i
=
0
;
i
<
size
-
3
;
i
++
)
{
if
(
buf
[
i
]
==
0x47
&&
!
(
buf
[
i
+
1
]
&
0x80
)
&&
(
buf
[
i
+
3
]
&
0x30
))
{
for
(
x
=
i
=
0
;
i
<
size
-
3
;
i
++
)
{
if
(
buf
[
i
]
==
0x47
&&
!
(
buf
[
i
+
1
]
&
0x80
)
&&
(
buf
[
i
+
3
]
&
0x30
))
{
stat
[
x
]
++
;
if
(
stat
[
x
]
>
best_score
){
best_score
=
stat
[
x
];
if
(
index
)
*
index
=
x
;
if
(
stat
[
x
]
>
best_score
)
{
best_score
=
stat
[
x
];
if
(
index
)
*
index
=
x
;
}
}
x
++
;
if
(
x
==
packet_size
)
x
=
0
;
if
(
x
==
packet_size
)
x
=
0
;
}
return
best_score
;
...
...
@@ -431,16 +442,20 @@ static int get_packet_size(const uint8_t *buf, int size)
if
(
size
<
(
TS_FEC_PACKET_SIZE
*
5
+
1
))
return
-
1
;
score
=
analyze
(
buf
,
size
,
TS_PACKET_SIZE
,
NULL
);
dvhs_score
=
analyze
(
buf
,
size
,
TS_DVHS_PACKET_SIZE
,
NULL
);
fec_score
=
analyze
(
buf
,
size
,
TS_FEC_PACKET_SIZE
,
NULL
);
score
=
analyze
(
buf
,
size
,
TS_PACKET_SIZE
,
NULL
);
dvhs_score
=
analyze
(
buf
,
size
,
TS_DVHS_PACKET_SIZE
,
NULL
);
fec_score
=
analyze
(
buf
,
size
,
TS_FEC_PACKET_SIZE
,
NULL
);
av_dlog
(
NULL
,
"score: %d, dvhs_score: %d, fec_score: %d
\n
"
,
score
,
dvhs_score
,
fec_score
);
if
(
score
>
fec_score
&&
score
>
dvhs_score
)
return
TS_PACKET_SIZE
;
else
if
(
dvhs_score
>
score
&&
dvhs_score
>
fec_score
)
return
TS_DVHS_PACKET_SIZE
;
else
if
(
score
<
fec_score
&&
dvhs_score
<
fec_score
)
return
TS_FEC_PACKET_SIZE
;
else
return
-
1
;
if
(
score
>
fec_score
&&
score
>
dvhs_score
)
return
TS_PACKET_SIZE
;
else
if
(
dvhs_score
>
score
&&
dvhs_score
>
fec_score
)
return
TS_DVHS_PACKET_SIZE
;
else
if
(
score
<
fec_score
&&
dvhs_score
<
fec_score
)
return
TS_FEC_PACKET_SIZE
;
else
return
-
1
;
}
typedef
struct
SectionHeader
{
...
...
@@ -459,7 +474,7 @@ static inline int get8(const uint8_t **pp, const uint8_t *p_end)
p
=
*
pp
;
if
(
p
>=
p_end
)
return
-
1
;
c
=
*
p
++
;
c
=
*
p
++
;
*
pp
=
p
;
return
c
;
}
...
...
@@ -472,8 +487,8 @@ static inline int get16(const uint8_t **pp, const uint8_t *p_end)
p
=
*
pp
;
if
((
p
+
1
)
>=
p_end
)
return
-
1
;
c
=
AV_RB16
(
p
);
p
+=
2
;
c
=
AV_RB16
(
p
);
p
+=
2
;
*
pp
=
p
;
return
c
;
}
...
...
@@ -485,7 +500,7 @@ static char *getstr8(const uint8_t **pp, const uint8_t *p_end)
const
uint8_t
*
p
;
char
*
str
;
p
=
*
pp
;
p
=
*
pp
;
len
=
get8
(
&
p
,
p_end
);
if
(
len
<
0
)
return
NULL
;
...
...
@@ -496,7 +511,7 @@ static char *getstr8(const uint8_t **pp, const uint8_t *p_end)
return
NULL
;
memcpy
(
str
,
p
,
len
);
str
[
len
]
=
'\0'
;
p
+=
len
;
p
+=
len
;
*
pp
=
p
;
return
str
;
}
...
...
@@ -511,7 +526,7 @@ static int parse_section_header(SectionHeader *h,
return
-
1
;
h
->
tid
=
val
;
*
pp
+=
2
;
val
=
get16
(
pp
,
p_end
);
val
=
get16
(
pp
,
p_end
);
if
(
val
<
0
)
return
-
1
;
h
->
id
=
val
;
...
...
@@ -539,86 +554,86 @@ typedef struct {
static
const
StreamType
ISO_types
[]
=
{
{
0x01
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_MPEG2VIDEO
},
{
0x02
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_MPEG2VIDEO
},
{
0x03
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_MP3
},
{
0x04
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_MP3
},
{
0x0f
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AAC
},
{
0x10
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_MPEG4
},
{
0x11
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AAC_LATM
},
/* LATM syntax */
{
0x1b
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_H264
},
{
0x24
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_HEVC
},
{
0x42
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_CAVS
},
{
0xd1
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_DIRAC
},
{
0xea
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_VC1
},
{
0x03
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_MP3
},
{
0x04
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_MP3
},
{
0x0f
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AAC
},
{
0x10
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_MPEG4
},
{
0x11
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AAC_LATM
},
/* LATM syntax */
{
0x1b
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_H264
},
{
0x24
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_HEVC
},
{
0x42
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_CAVS
},
{
0xd1
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_DIRAC
},
{
0xea
,
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_VC1
},
{
0
},
};
static
const
StreamType
HDMV_types
[]
=
{
{
0x80
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_PCM_BLURAY
},
{
0x81
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AC3
},
{
0x82
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
0x83
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_TRUEHD
},
{
0x84
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_EAC3
},
{
0x85
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
/* DTS HD */
{
0x86
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
/* DTS HD MASTER*/
{
0x80
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_PCM_BLURAY
},
{
0x81
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AC3
},
{
0x82
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
0x83
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_TRUEHD
},
{
0x84
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_EAC3
},
{
0x85
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
/* DTS HD */
{
0x86
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
/* DTS HD MASTER*/
{
0x90
,
AVMEDIA_TYPE_SUBTITLE
,
AV_CODEC_ID_HDMV_PGS_SUBTITLE
},
{
0
},
};
/* ATSC ? */
static
const
StreamType
MISC_types
[]
=
{
{
0x81
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AC3
},
{
0x8a
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
0x81
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AC3
},
{
0x8a
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
0
},
};
static
const
StreamType
REGD_types
[]
=
{
{
MKTAG
(
'd'
,
'r'
,
'a'
,
'c'
),
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_DIRAC
},
{
MKTAG
(
'A'
,
'C'
,
'-'
,
'3'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AC3
},
{
MKTAG
(
'B'
,
'S'
,
'S'
,
'D'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_S302M
},
{
MKTAG
(
'D'
,
'T'
,
'S'
,
'1'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
MKTAG
(
'D'
,
'T'
,
'S'
,
'2'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
MKTAG
(
'D'
,
'T'
,
'S'
,
'3'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
MKTAG
(
'H'
,
'E'
,
'V'
,
'C'
),
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_HEVC
},
{
MKTAG
(
'V'
,
'C'
,
'-'
,
'1'
),
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_VC1
},
{
MKTAG
(
'd'
,
'r'
,
'a'
,
'c'
),
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_DIRAC
},
{
MKTAG
(
'A'
,
'C'
,
'-'
,
'3'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AC3
},
{
MKTAG
(
'B'
,
'S'
,
'S'
,
'D'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_S302M
},
{
MKTAG
(
'D'
,
'T'
,
'S'
,
'1'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
MKTAG
(
'D'
,
'T'
,
'S'
,
'2'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
MKTAG
(
'D'
,
'T'
,
'S'
,
'3'
),
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
MKTAG
(
'H'
,
'E'
,
'V'
,
'C'
),
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_HEVC
},
{
MKTAG
(
'V'
,
'C'
,
'-'
,
'1'
),
AVMEDIA_TYPE_VIDEO
,
AV_CODEC_ID_VC1
},
{
0
},
};
/* descriptor present */
static
const
StreamType
DESC_types
[]
=
{
{
0x6a
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AC3
},
/* AC-3 descriptor */
{
0x7a
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_EAC3
},
/* E-AC-3 descriptor */
{
0x7b
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
0x6a
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_AC3
},
/* AC-3 descriptor */
{
0x7a
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_EAC3
},
/* E-AC-3 descriptor */
{
0x7b
,
AVMEDIA_TYPE_AUDIO
,
AV_CODEC_ID_DTS
},
{
0x56
,
AVMEDIA_TYPE_SUBTITLE
,
AV_CODEC_ID_DVB_TELETEXT
},
{
0x59
,
AVMEDIA_TYPE_SUBTITLE
,
AV_CODEC_ID_DVB_SUBTITLE
},
/* subtitling descriptor */
{
0
},
};
static
void
mpegts_find_stream_type
(
AVStream
*
st
,
uint32_t
stream_type
,
const
StreamType
*
types
)
uint32_t
stream_type
,
const
StreamType
*
types
)
{
for
(;
types
->
stream_type
;
types
++
)
{
for
(;
types
->
stream_type
;
types
++
)
if
(
stream_type
==
types
->
stream_type
)
{
st
->
codec
->
codec_type
=
types
->
codec_type
;
st
->
codec
->
codec_id
=
types
->
codec_id
;
return
;
}
}
}
static
int
mpegts_set_stream_info
(
AVStream
*
st
,
PESContext
*
pes
,
uint32_t
stream_type
,
uint32_t
prog_reg_desc
)
{
avpriv_set_pts_info
(
st
,
33
,
1
,
90000
);
st
->
priv_data
=
pes
;
st
->
priv_data
=
pes
;
st
->
codec
->
codec_type
=
AVMEDIA_TYPE_DATA
;
st
->
codec
->
codec_id
=
AV_CODEC_ID_NONE
;
st
->
need_parsing
=
AVSTREAM_PARSE_FULL
;
pes
->
st
=
st
;
st
->
need_parsing
=
AVSTREAM_PARSE_FULL
;
pes
->
st
=
st
;
pes
->
stream_type
=
stream_type
;
av_log
(
pes
->
stream
,
AV_LOG_DEBUG
,
"stream=%d stream_type=%x pid=%x prog_reg_desc=%.4s
\n
"
,
st
->
index
,
pes
->
stream_type
,
pes
->
pid
,
(
char
*
)
&
prog_reg_desc
);
st
->
index
,
pes
->
stream_type
,
pes
->
pid
,
(
char
*
)
&
prog_reg_desc
);
st
->
codec
->
codec_tag
=
pes
->
stream_type
;
...
...
@@ -644,11 +659,11 @@ static int mpegts_set_stream_info(AVStream *st, PESContext *pes,
sub_st
->
id
=
pes
->
pid
;
avpriv_set_pts_info
(
sub_st
,
33
,
1
,
90000
);
sub_st
->
priv_data
=
sub_pes
;
sub_st
->
priv_data
=
sub_pes
;
sub_st
->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
sub_st
->
codec
->
codec_id
=
AV_CODEC_ID_AC3
;
sub_st
->
need_parsing
=
AVSTREAM_PARSE_FULL
;
sub_pes
->
sub_st
=
pes
->
sub_st
=
sub_st
;
sub_st
->
need_parsing
=
AVSTREAM_PARSE_FULL
;
sub_pes
->
sub_st
=
pes
->
sub_st
=
sub_st
;
}
}
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_NONE
)
...
...
@@ -665,12 +680,13 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
pkt
->
data
=
pes
->
buffer
->
data
;
pkt
->
size
=
pes
->
data_index
;
if
(
pes
->
total_size
!=
MAX_PES_PAYLOAD
&&
pes
->
pes_header_size
+
pes
->
data_index
!=
pes
->
total_size
+
PES_START_SIZE
)
{
if
(
pes
->
total_size
!=
MAX_PES_PAYLOAD
&&
pes
->
pes_header_size
+
pes
->
data_index
!=
pes
->
total_size
+
PES_START_SIZE
)
{
av_log
(
pes
->
stream
,
AV_LOG_WARNING
,
"PES packet size mismatch
\n
"
);
pes
->
flags
|=
AV_PKT_FLAG_CORRUPT
;
}
memset
(
pkt
->
data
+
pkt
->
size
,
0
,
FF_INPUT_BUFFER_PADDING_SIZE
);
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
)
...
...
@@ -680,25 +696,26 @@ static void new_pes_packet(PESContext *pes, AVPacket *pkt)
pkt
->
pts
=
pes
->
pts
;
pkt
->
dts
=
pes
->
dts
;
/* store position of first TS packet of this PES packet */
pkt
->
pos
=
pes
->
ts_packet_pos
;
pkt
->
pos
=
pes
->
ts_packet_pos
;
pkt
->
flags
=
pes
->
flags
;
/* reset pts values */
pes
->
pts
=
AV_NOPTS_VALUE
;
pes
->
dts
=
AV_NOPTS_VALUE
;
pes
->
buffer
=
NULL
;
pes
->
pts
=
AV_NOPTS_VALUE
;
pes
->
dts
=
AV_NOPTS_VALUE
;
pes
->
buffer
=
NULL
;
pes
->
data_index
=
0
;
pes
->
flags
=
0
;
pes
->
flags
=
0
;
}
static
int
read_sl_header
(
PESContext
*
pes
,
SLConfigDescr
*
sl
,
const
uint8_t
*
buf
,
int
buf_size
)
static
int
read_sl_header
(
PESContext
*
pes
,
SLConfigDescr
*
sl
,
const
uint8_t
*
buf
,
int
buf_size
)
{
GetBitContext
gb
;
int
au_start_flag
=
0
,
au_end_flag
=
0
,
ocr_flag
=
0
,
idle_flag
=
0
;
int
padding_flag
=
0
,
padding_bits
=
0
,
inst_bitrate_flag
=
0
;
int
dts_flag
=
-
1
,
cts_flag
=
-
1
;
int64_t
dts
=
AV_NOPTS_VALUE
,
cts
=
AV_NOPTS_VALUE
;
init_get_bits
(
&
gb
,
buf
,
buf_size
*
8
);
init_get_bits
(
&
gb
,
buf
,
buf_size
*
8
);
if
(
sl
->
use_au_start
)
au_start_flag
=
get_bits1
(
&
gb
);
...
...
@@ -761,12 +778,12 @@ 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
;
PESContext
*
pes
=
filter
->
u
.
pes_filter
.
opaque
;
MpegTSContext
*
ts
=
pes
->
ts
;
const
uint8_t
*
p
;
int
len
,
code
;
if
(
!
ts
->
pkt
)
if
(
!
ts
->
pkt
)
return
0
;
if
(
is_start
)
{
...
...
@@ -774,13 +791,13 @@ static int mpegts_push_data(MpegTSFilter *filter,
new_pes_packet
(
pes
,
ts
->
pkt
);
ts
->
stop_parse
=
1
;
}
pes
->
state
=
MPEGTS_HEADER
;
pes
->
data_index
=
0
;
pes
->
state
=
MPEGTS_HEADER
;
pes
->
data_index
=
0
;
pes
->
ts_packet_pos
=
pos
;
}
p
=
buf
;
while
(
buf_size
>
0
)
{
switch
(
pes
->
state
)
{
switch
(
pes
->
state
)
{
case
MPEGTS_HEADER
:
len
=
PES_START_SIZE
-
pes
->
data_index
;
if
(
len
>
buf_size
)
...
...
@@ -791,15 +808,17 @@ static int mpegts_push_data(MpegTSFilter *filter,
buf_size
-=
len
;
if
(
pes
->
data_index
==
PES_START_SIZE
)
{
/* we got all the PES or section header. We can now
decide */
*
decide */
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
;
av_dlog
(
pes
->
stream
,
"pid=%x pes_code=%#x
\n
"
,
pes
->
pid
,
code
);
av_dlog
(
pes
->
stream
,
"pid=%x pes_code=%#x
\n
"
,
pes
->
pid
,
code
);
if
((
pes
->
st
&&
pes
->
st
->
discard
==
AVDISCARD_ALL
&&
(
!
pes
->
sub_st
||
pes
->
sub_st
->
discard
==
AVDISCARD_ALL
))
||
(
!
pes
->
sub_st
||
pes
->
sub_st
->
discard
==
AVDISCARD_ALL
))
||
code
==
0x1be
)
/* padding_stream */
goto
skip
;
...
...
@@ -814,7 +833,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
pes
->
total_size
=
AV_RB16
(
pes
->
header
+
4
);
/* NOTE: a zero total size means the PES size is
unbounded */
*
unbounded */
if
(
!
pes
->
total_size
)
pes
->
total_size
=
MAX_PES_PAYLOAD
;
...
...
@@ -830,25 +849,27 @@ static int mpegts_push_data(MpegTSFilter *filter,
code
!=
0x1f8
)
{
/* ITU-T Rec. H.222.1 type E stream */
pes
->
state
=
MPEGTS_PESHEADER
;
if
(
pes
->
st
->
codec
->
codec_id
==
AV_CODEC_ID_NONE
)
{
av_dlog
(
pes
->
stream
,
"pid=%x stream_type=%x probing
\n
"
,
pes
->
pid
,
pes
->
stream_type
);
av_dlog
(
pes
->
stream
,
"pid=%x stream_type=%x probing
\n
"
,
pes
->
pid
,
pes
->
stream_type
);
pes
->
st
->
codec
->
codec_id
=
AV_CODEC_ID_PROBE
;
}
}
else
{
pes
->
state
=
MPEGTS_PAYLOAD
;
pes
->
state
=
MPEGTS_PAYLOAD
;
pes
->
data_index
=
0
;
}
}
else
{
/* otherwise, it should be a table */
/* skip packet */
skip:
skip:
pes
->
state
=
MPEGTS_SKIP
;
continue
;
}
}
break
;
/**********************************************/
/* PES packing parsing */
/**********************************************/
/* PES packing parsing */
case
MPEGTS_PESHEADER
:
len
=
PES_HEADER_SIZE
-
pes
->
data_index
;
if
(
len
<
0
)
...
...
@@ -861,7 +882,7 @@ static int mpegts_push_data(MpegTSFilter *filter,
buf_size
-=
len
;
if
(
pes
->
data_index
==
PES_HEADER_SIZE
)
{
pes
->
pes_header_size
=
pes
->
header
[
8
]
+
9
;
pes
->
state
=
MPEGTS_PESHEADER_FILL
;
pes
->
state
=
MPEGTS_PESHEADER_FILL
;
}
break
;
case
MPEGTS_PESHEADER_FILL
:
...
...
@@ -895,9 +916,9 @@ static int mpegts_push_data(MpegTSFilter *filter,
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
=
(
pes_ext
>>
4
)
&
0xb
;
skip
+=
skip
&
0x9
;
r
+=
skip
;
r
+=
skip
;
if
((
pes_ext
&
0x41
)
==
0x01
&&
(
r
+
2
)
<=
(
pes
->
header
+
pes
->
pes_header_size
))
{
/* PES extension 2 */
...
...
@@ -910,7 +931,8 @@ static int mpegts_push_data(MpegTSFilter *filter,
pes
->
state
=
MPEGTS_PAYLOAD
;
pes
->
data_index
=
0
;
if
(
pes
->
stream_type
==
0x12
&&
buf_size
>
0
)
{
int
sl_header_bytes
=
read_sl_header
(
pes
,
&
pes
->
sl
,
p
,
buf_size
);
int
sl_header_bytes
=
read_sl_header
(
pes
,
&
pes
->
sl
,
p
,
buf_size
);
pes
->
pes_header_size
+=
sl_header_bytes
;
p
+=
sl_header_bytes
;
buf_size
-=
sl_header_bytes
;
...
...
@@ -919,14 +941,17 @@ static int mpegts_push_data(MpegTSFilter *filter,
break
;
case
MPEGTS_PAYLOAD
:
if
(
buf_size
>
0
&&
pes
->
buffer
)
{
if
(
pes
->
data_index
>
0
&&
pes
->
data_index
+
buf_size
>
pes
->
total_size
)
{
if
(
pes
->
data_index
>
0
&&
pes
->
data_index
+
buf_size
>
pes
->
total_size
)
{
new_pes_packet
(
pes
,
ts
->
pkt
);
pes
->
total_size
=
MAX_PES_PAYLOAD
;
pes
->
buffer
=
av_buffer_alloc
(
pes
->
total_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
pes
->
buffer
=
av_buffer_alloc
(
pes
->
total_size
+
FF_INPUT_BUFFER_PADDING_SIZE
);
if
(
!
pes
->
buffer
)
return
AVERROR
(
ENOMEM
);
ts
->
stop_parse
=
1
;
}
else
if
(
pes
->
data_index
==
0
&&
buf_size
>
pes
->
total_size
)
{
}
else
if
(
pes
->
data_index
==
0
&&
buf_size
>
pes
->
total_size
)
{
// pes packet size is < ts size packet and pes data is padded with 0xff
// not sure if this is legal in ts but see issue #2392
buf_size
=
pes
->
total_size
;
...
...
@@ -964,14 +989,14 @@ static PESContext *add_pes_stream(MpegTSContext *ts, int pid, int pcr_pid)
pes
=
av_mallocz
(
sizeof
(
PESContext
));
if
(
!
pes
)
return
0
;
pes
->
ts
=
ts
;
pes
->
stream
=
ts
->
stream
;
pes
->
pid
=
pid
;
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
);
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
;
...
...
@@ -990,32 +1015,33 @@ typedef struct {
int
level
;
}
MP4DescrParseContext
;
static
int
init_MP4DescrParseContext
(
MP4DescrParseContext
*
d
,
AVFormatContext
*
s
,
const
uint8_t
*
buf
,
unsigned
size
,
Mp4Descr
*
descr
,
int
max_descr_count
)
static
int
init_MP4DescrParseContext
(
MP4DescrParseContext
*
d
,
AVFormatContext
*
s
,
const
uint8_t
*
buf
,
unsigned
size
,
Mp4Descr
*
descr
,
int
max_descr_count
)
{
int
ret
;
if
(
size
>
(
1
<<
30
))
if
(
size
>
(
1
<<
30
))
return
AVERROR_INVALIDDATA
;
if
((
ret
=
ffio_init_context
(
&
d
->
pb
,
(
unsigned
char
*
)
buf
,
size
,
0
,
NULL
,
NULL
,
NULL
,
NULL
))
<
0
)
if
((
ret
=
ffio_init_context
(
&
d
->
pb
,
(
unsigned
char
*
)
buf
,
size
,
0
,
NULL
,
NULL
,
NULL
,
NULL
))
<
0
)
return
ret
;
d
->
s
=
s
;
d
->
level
=
0
;
d
->
descr_count
=
0
;
d
->
descr
=
descr
;
d
->
active_descr
=
NULL
;
d
->
s
=
s
;
d
->
level
=
0
;
d
->
descr_count
=
0
;
d
->
descr
=
descr
;
d
->
active_descr
=
NULL
;
d
->
max_descr_count
=
max_descr_count
;
return
0
;
}
static
void
update_offsets
(
AVIOContext
*
pb
,
int64_t
*
off
,
int
*
len
)
{
static
void
update_offsets
(
AVIOContext
*
pb
,
int64_t
*
off
,
int
*
len
)
{
int64_t
new_off
=
avio_tell
(
pb
);
(
*
len
)
-=
new_off
-
*
off
;
*
off
=
new_off
;
*
off
=
new_off
;
}
static
int
parse_mp4_descr
(
MP4DescrParseContext
*
d
,
int64_t
off
,
int
len
,
...
...
@@ -1049,9 +1075,9 @@ static int parse_MP4ODescrTag(MP4DescrParseContext *d, int64_t off, int len)
if
(
len
<
2
)
return
0
;
id_flags
=
avio_rb16
(
&
d
->
pb
);
if
(
!
(
id_flags
&
0x0020
))
{
//URL_Flag
if
(
!
(
id_flags
&
0x0020
))
{
//
URL_Flag
update_offsets
(
&
d
->
pb
,
&
off
,
&
len
);
return
parse_mp4_descr_arr
(
d
,
off
,
len
);
//ES_Descriptor[]
return
parse_mp4_descr_arr
(
d
,
off
,
len
);
//
ES_Descriptor[]
}
else
{
return
0
;
}
...
...
@@ -1075,7 +1101,8 @@ static int parse_MP4ESDescrTag(MP4DescrParseContext *d, int64_t off, int len)
return
0
;
}
static
int
parse_MP4DecConfigDescrTag
(
MP4DescrParseContext
*
d
,
int64_t
off
,
int
len
)
static
int
parse_MP4DecConfigDescrTag
(
MP4DescrParseContext
*
d
,
int64_t
off
,
int
len
)
{
Mp4Descr
*
descr
=
d
->
active_descr
;
if
(
!
descr
)
...
...
@@ -1099,14 +1126,14 @@ static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len)
if
(
!
predefined
)
{
int
lengths
;
int
flags
=
avio_r8
(
&
d
->
pb
);
descr
->
sl
.
use_au_start
=
!!
(
flags
&
0x80
);
descr
->
sl
.
use_au_end
=
!!
(
flags
&
0x40
);
descr
->
sl
.
use_rand_acc_pt
=
!!
(
flags
&
0x20
);
descr
->
sl
.
use_padding
=
!!
(
flags
&
0x08
);
descr
->
sl
.
use_timestamps
=
!!
(
flags
&
0x04
);
descr
->
sl
.
use_idle
=
!!
(
flags
&
0x02
);
descr
->
sl
.
timestamp_res
=
avio_rb32
(
&
d
->
pb
);
avio_rb32
(
&
d
->
pb
);
descr
->
sl
.
use_au_start
=
!!
(
flags
&
0x80
);
descr
->
sl
.
use_au_end
=
!!
(
flags
&
0x40
);
descr
->
sl
.
use_rand_acc_pt
=
!!
(
flags
&
0x20
);
descr
->
sl
.
use_padding
=
!!
(
flags
&
0x08
);
descr
->
sl
.
use_timestamps
=
!!
(
flags
&
0x04
);
descr
->
sl
.
use_idle
=
!!
(
flags
&
0x02
);
descr
->
sl
.
timestamp_res
=
avio_rb32
(
&
d
->
pb
);
avio_rb32
(
&
d
->
pb
);
descr
->
sl
.
timestamp_len
=
avio_r8
(
&
d
->
pb
);
descr
->
sl
.
ocr_len
=
avio_r8
(
&
d
->
pb
);
descr
->
sl
.
au_len
=
avio_r8
(
&
d
->
pb
);
...
...
@@ -1122,12 +1149,15 @@ static int parse_MP4SLDescrTag(MP4DescrParseContext *d, int64_t off, int len)
}
static
int
parse_mp4_descr
(
MP4DescrParseContext
*
d
,
int64_t
off
,
int
len
,
int
target_tag
)
{
int
target_tag
)
{
int
tag
;
int
len1
=
ff_mp4_read_descr
(
d
->
s
,
&
d
->
pb
,
&
tag
);
update_offsets
(
&
d
->
pb
,
&
off
,
&
len
);
if
(
len
<
0
||
len1
>
len
||
len1
<=
0
)
{
av_log
(
d
->
s
,
AV_LOG_ERROR
,
"Tag %x length violation new length %d bytes remaining %d
\n
"
,
tag
,
len1
,
len
);
av_log
(
d
->
s
,
AV_LOG_ERROR
,
"Tag %x length violation new length %d bytes remaining %d
\n
"
,
tag
,
len1
,
len
);
return
-
1
;
}
...
...
@@ -1137,7 +1167,8 @@ static int parse_mp4_descr(MP4DescrParseContext *d, int64_t off, int len,
}
if
(
target_tag
&&
tag
!=
target_tag
)
{
av_log
(
d
->
s
,
AV_LOG_ERROR
,
"Found tag %x expected %x
\n
"
,
tag
,
target_tag
);
av_log
(
d
->
s
,
AV_LOG_ERROR
,
"Found tag %x expected %x
\n
"
,
tag
,
target_tag
);
goto
done
;
}
...
...
@@ -1191,14 +1222,15 @@ static int mp4_read_od(AVFormatContext *s, const uint8_t *buf, unsigned size,
return
0
;
}
static
void
m4sl_cb
(
MpegTSFilter
*
filter
,
const
uint8_t
*
section
,
int
section_len
)
static
void
m4sl_cb
(
MpegTSFilter
*
filter
,
const
uint8_t
*
section
,
int
section_len
)
{
MpegTSContext
*
ts
=
filter
->
u
.
section_filter
.
opaque
;
SectionHeader
h
;
const
uint8_t
*
p
,
*
p_end
;
AVIOContext
pb
;
Mp4Descr
mp4_descr
[
MAX_MP4_DESCR_COUNT
]
=
{{
0
}};
int
mp4_descr_count
=
0
;
Mp4Descr
mp4_descr
[
MAX_MP4_DESCR_COUNT
]
=
{
{
0
}
};
int
i
,
pid
;
AVFormatContext
*
s
=
ts
->
stream
;
...
...
@@ -1209,11 +1241,12 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le
if
(
h
.
tid
!=
M4OD_TID
)
return
;
mp4_read_od
(
s
,
p
,
(
unsigned
)(
p_end
-
p
),
mp4_descr
,
&
mp4_descr_count
,
MAX_MP4_DESCR_COUNT
);
mp4_read_od
(
s
,
p
,
(
unsigned
)
(
p_end
-
p
),
mp4_descr
,
&
mp4_descr_count
,
MAX_MP4_DESCR_COUNT
);
for
(
pid
=
0
;
pid
<
NB_PID_MAX
;
pid
++
)
{
if
(
!
ts
->
pids
[
pid
])
continue
;
continue
;
for
(
i
=
0
;
i
<
mp4_descr_count
;
i
++
)
{
PESContext
*
pes
;
AVStream
*
st
;
...
...
@@ -1224,15 +1257,15 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le
continue
;
}
pes
=
ts
->
pids
[
pid
]
->
u
.
pes_filter
.
opaque
;
st
=
pes
->
st
;
if
(
!
st
)
{
st
=
pes
->
st
;
if
(
!
st
)
continue
;
}
pes
->
sl
=
mp4_descr
[
i
].
sl
;
ffio_init_context
(
&
pb
,
mp4_descr
[
i
].
dec_config_descr
,
mp4_descr
[
i
].
dec_config_descr_len
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
mp4_descr
[
i
].
dec_config_descr_len
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
ff_mp4_read_dec_config_descr
(
s
,
st
,
&
pb
);
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_AAC
&&
st
->
codec
->
extradata_size
>
0
)
...
...
@@ -1242,13 +1275,13 @@ static void m4sl_cb(MpegTSFilter *filter, const uint8_t *section, int section_le
st
->
need_parsing
=
0
;
if
(
st
->
codec
->
codec_id
<=
AV_CODEC_ID_NONE
)
{
}
else
if
(
st
->
codec
->
codec_id
<
AV_CODEC_ID_FIRST_AUDIO
)
{
// do nothing
}
else
if
(
st
->
codec
->
codec_id
<
AV_CODEC_ID_FIRST_AUDIO
)
st
->
codec
->
codec_type
=
AVMEDIA_TYPE_VIDEO
;
}
else
if
(
st
->
codec
->
codec_id
<
AV_CODEC_ID_FIRST_SUBTITLE
)
{
else
if
(
st
->
codec
->
codec_id
<
AV_CODEC_ID_FIRST_SUBTITLE
)
st
->
codec
->
codec_type
=
AVMEDIA_TYPE_AUDIO
;
}
else
if
(
st
->
codec
->
codec_id
<
AV_CODEC_ID_FIRST_UNKNOWN
)
{
else
if
(
st
->
codec
->
codec_id
<
AV_CODEC_ID_FIRST_UNKNOWN
)
st
->
codec
->
codec_type
=
AVMEDIA_TYPE_SUBTITLE
;
}
}
}
for
(
i
=
0
;
i
<
mp4_descr_count
;
i
++
)
...
...
@@ -1281,32 +1314,35 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
stream_type
==
STREAM_TYPE_PRIVATE_DATA
)
mpegts_find_stream_type
(
st
,
desc_tag
,
DESC_types
);
switch
(
desc_tag
)
{
switch
(
desc_tag
)
{
case
0x1E
:
/* SL descriptor */
desc_es_id
=
get16
(
pp
,
desc_end
);
if
(
ts
&&
ts
->
pids
[
pid
])
ts
->
pids
[
pid
]
->
es_id
=
desc_es_id
;
for
(
i
=
0
;
i
<
mp4_descr_count
;
i
++
)
if
(
mp4_descr
[
i
].
dec_config_descr_len
&&
mp4_descr
[
i
].
es_id
==
desc_es_id
)
{
AVIOContext
pb
;
ffio_init_context
(
&
pb
,
mp4_descr
[
i
].
dec_config_descr
,
mp4_descr
[
i
].
dec_config_descr_len
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
ff_mp4_read_dec_config_descr
(
fc
,
st
,
&
pb
);
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_AAC
&&
st
->
codec
->
extradata_size
>
0
)
st
->
need_parsing
=
0
;
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_MPEG4SYSTEMS
)
mpegts_open_section_filter
(
ts
,
pid
,
m4sl_cb
,
ts
,
1
);
}
if
(
mp4_descr
[
i
].
dec_config_descr_len
&&
mp4_descr
[
i
].
es_id
==
desc_es_id
)
{
AVIOContext
pb
;
ffio_init_context
(
&
pb
,
mp4_descr
[
i
].
dec_config_descr
,
mp4_descr
[
i
].
dec_config_descr_len
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
ff_mp4_read_dec_config_descr
(
fc
,
st
,
&
pb
);
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_AAC
&&
st
->
codec
->
extradata_size
>
0
)
st
->
need_parsing
=
0
;
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_MPEG4SYSTEMS
)
mpegts_open_section_filter
(
ts
,
pid
,
m4sl_cb
,
ts
,
1
);
}
break
;
case
0x1F
:
/* FMC descriptor */
get16
(
pp
,
desc_end
);
if
(
mp4_descr_count
>
0
&&
st
->
codec
->
codec_id
==
AV_CODEC_ID_AAC_LATM
&&
if
(
mp4_descr_count
>
0
&&
st
->
codec
->
codec_id
==
AV_CODEC_ID_AAC_LATM
&&
mp4_descr
->
dec_config_descr_len
&&
mp4_descr
->
es_id
==
pid
)
{
AVIOContext
pb
;
ffio_init_context
(
&
pb
,
mp4_descr
->
dec_config_descr
,
mp4_descr
->
dec_config_descr_len
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
mp4_descr
->
dec_config_descr_len
,
0
,
NULL
,
NULL
,
NULL
,
NULL
);
ff_mp4_read_dec_config_descr
(
fc
,
st
,
&
pb
);
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_AAC
&&
st
->
codec
->
extradata_size
>
0
)
...
...
@@ -1326,7 +1362,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
language
[
2
]
=
get8
(
pp
,
desc_end
);
language
[
3
]
=
0
;
/* hearing impaired subtitles detection */
switch
(
get8
(
pp
,
desc_end
))
{
switch
(
get8
(
pp
,
desc_end
))
{
case
0x20
:
/* DVB subtitles (for the hard of hearing) with no monitor aspect ratio criticality */
case
0x21
:
/* DVB subtitles (for the hard of hearing) for display on 4:3 aspect ratio monitor */
case
0x22
:
/* DVB subtitles (for the hard of hearing) for display on 16:9 aspect ratio monitor */
...
...
@@ -1337,7 +1373,8 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
break
;
}
if
(
st
->
codec
->
extradata
)
{
if
(
st
->
codec
->
extradata_size
==
4
&&
memcmp
(
st
->
codec
->
extradata
,
*
pp
,
4
))
if
(
st
->
codec
->
extradata_size
==
4
&&
memcmp
(
st
->
codec
->
extradata
,
*
pp
,
4
))
avpriv_request_sample
(
fc
,
"DVB sub with multiple IDs"
);
}
else
{
st
->
codec
->
extradata
=
av_malloc
(
4
+
FF_INPUT_BUFFER_PADDING_SIZE
);
...
...
@@ -1355,11 +1392,17 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
language
[
i
+
1
]
=
get8
(
pp
,
desc_end
);
language
[
i
+
2
]
=
get8
(
pp
,
desc_end
);
language
[
i
+
3
]
=
','
;
switch
(
get8
(
pp
,
desc_end
))
{
case
0x01
:
st
->
disposition
|=
AV_DISPOSITION_CLEAN_EFFECTS
;
break
;
case
0x02
:
st
->
disposition
|=
AV_DISPOSITION_HEARING_IMPAIRED
;
break
;
case
0x03
:
st
->
disposition
|=
AV_DISPOSITION_VISUAL_IMPAIRED
;
break
;
}
switch
(
get8
(
pp
,
desc_end
))
{
case
0x01
:
st
->
disposition
|=
AV_DISPOSITION_CLEAN_EFFECTS
;
break
;
case
0x02
:
st
->
disposition
|=
AV_DISPOSITION_HEARING_IMPAIRED
;
break
;
case
0x03
:
st
->
disposition
|=
AV_DISPOSITION_VISUAL_IMPAIRED
;
break
;
}
}
if
(
i
)
{
language
[
i
-
1
]
=
0
;
...
...
@@ -1368,7 +1411,7 @@ int ff_parse_mpeg2_descriptor(AVFormatContext *fc, AVStream *st, int stream_type
break
;
case
0x05
:
/* registration descriptor */
st
->
codec
->
codec_tag
=
bytestream_get_le32
(
pp
);
av_dlog
(
fc
,
"reg_desc=%.4s
\n
"
,
(
char
*
)
&
st
->
codec
->
codec_tag
);
av_dlog
(
fc
,
"reg_desc=%.4s
\n
"
,
(
char
*
)
&
st
->
codec
->
codec_tag
);
if
(
st
->
codec
->
codec_id
==
AV_CODEC_ID_NONE
)
mpegts_find_stream_type
(
st
,
st
->
codec
->
codec_tag
,
REGD_types
);
break
;
...
...
@@ -1390,8 +1433,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
int
desc_list_len
;
uint32_t
prog_reg_desc
=
0
;
/* registration descriptor */
Mp4Descr
mp4_descr
[
MAX_MP4_DESCR_COUNT
]
=
{{
0
}};
int
mp4_descr_count
=
0
;
Mp4Descr
mp4_descr
[
MAX_MP4_DESCR_COUNT
]
=
{
{
0
}
};
int
i
;
av_dlog
(
ts
->
stream
,
"PMT: len %i
\n
"
,
section_len
);
...
...
@@ -1403,7 +1446,7 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
return
;
av_dlog
(
ts
->
stream
,
"sid=0x%x sec_num=%d/%d
\n
"
,
h
->
id
,
h
->
sec_num
,
h
->
last_sec_num
);
h
->
id
,
h
->
sec_num
,
h
->
last_sec_num
);
if
(
h
->
tid
!=
PMT_TID
)
return
;
...
...
@@ -1421,15 +1464,15 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if
(
program_info_length
<
0
)
return
;
program_info_length
&=
0xfff
;
while
(
program_info_length
>=
2
)
{
while
(
program_info_length
>=
2
)
{
uint8_t
tag
,
len
;
tag
=
get8
(
&
p
,
p_end
);
len
=
get8
(
&
p
,
p_end
);
av_dlog
(
ts
->
stream
,
"program tag: 0x%02x len=%d
\n
"
,
tag
,
len
);
if
(
len
>
program_info_length
-
2
)
//something else is broken, exit the program_descriptors_loop
if
(
len
>
program_info_length
-
2
)
//
something else is broken, exit the program_descriptors_loop
break
;
program_info_length
-=
len
+
2
;
if
(
tag
==
0x1d
)
{
// IOD descriptor
...
...
@@ -1452,7 +1495,8 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if
(
!
ts
->
stream
->
nb_streams
)
ts
->
stop_parse
=
1
;
for
(;;)
{
for
(;;)
{
st
=
0
;
pes
=
NULL
;
stream_type
=
get8
(
&
p
,
p_end
);
...
...
@@ -1467,12 +1511,13 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if
(
ts
->
pids
[
pid
]
&&
ts
->
pids
[
pid
]
->
type
==
MPEGTS_PES
)
{
pes
=
ts
->
pids
[
pid
]
->
u
.
pes_filter
.
opaque
;
if
(
!
pes
->
st
)
{
pes
->
st
=
avformat_new_stream
(
pes
->
stream
,
NULL
);
pes
->
st
=
avformat_new_stream
(
pes
->
stream
,
NULL
);
pes
->
st
->
id
=
pes
->
pid
;
}
st
=
pes
->
st
;
}
else
if
(
stream_type
!=
0x13
)
{
if
(
ts
->
pids
[
pid
])
mpegts_close_filter
(
ts
,
ts
->
pids
[
pid
]);
//wrongly added sdt filter probably
if
(
ts
->
pids
[
pid
])
mpegts_close_filter
(
ts
,
ts
->
pids
[
pid
]);
// wrongly added sdt filter probably
pes
=
add_pes_stream
(
ts
,
pid
,
pcr_pid
);
if
(
pes
)
{
st
=
avformat_new_stream
(
pes
->
stream
,
NULL
);
...
...
@@ -1503,23 +1548,26 @@ static void pmt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if
(
desc_list_len
<
0
)
break
;
desc_list_len
&=
0xfff
;
desc_list_end
=
p
+
desc_list_len
;
desc_list_end
=
p
+
desc_list_len
;
if
(
desc_list_end
>
p_end
)
break
;
for
(;;)
{
if
(
ff_parse_mpeg2_descriptor
(
ts
->
stream
,
st
,
stream_type
,
&
p
,
desc_list_end
,
mp4_descr
,
mp4_descr_count
,
pid
,
ts
)
<
0
)
for
(;;)
{
if
(
ff_parse_mpeg2_descriptor
(
ts
->
stream
,
st
,
stream_type
,
&
p
,
desc_list_end
,
mp4_descr
,
mp4_descr_count
,
pid
,
ts
)
<
0
)
break
;
if
(
pes
&&
prog_reg_desc
==
AV_RL32
(
"HDMV"
)
&&
stream_type
==
0x83
&&
pes
->
sub_st
)
{
ff_program_add_stream_index
(
ts
->
stream
,
h
->
id
,
pes
->
sub_st
->
index
);
if
(
pes
&&
prog_reg_desc
==
AV_RL32
(
"HDMV"
)
&&
stream_type
==
0x83
&&
pes
->
sub_st
)
{
ff_program_add_stream_index
(
ts
->
stream
,
h
->
id
,
pes
->
sub_st
->
index
);
pes
->
sub_st
->
codec
->
codec_tag
=
st
->
codec
->
codec_tag
;
}
}
p
=
desc_list_end
;
}
out:
out:
for
(
i
=
0
;
i
<
mp4_descr_count
;
i
++
)
av_free
(
mp4_descr
[
i
].
dec_config_descr
);
}
...
...
@@ -1535,14 +1583,14 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
hex_dump_debug
(
ts
->
stream
,
section
,
section_len
);
p_end
=
section
+
section_len
-
4
;
p
=
section
;
p
=
section
;
if
(
parse_section_header
(
h
,
&
p
,
p_end
)
<
0
)
return
;
if
(
h
->
tid
!=
PAT_TID
)
return
;
clear_programs
(
ts
);
for
(;;)
{
for
(;;)
{
sid
=
get16
(
&
p
,
p_end
);
if
(
sid
<
0
)
break
;
...
...
@@ -1561,7 +1609,7 @@ static void pat_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
mpegts_close_filter
(
ts
,
ts
->
pids
[
pmt_pid
]);
mpegts_open_section_filter
(
ts
,
pmt_pid
,
pmt_cb
,
ts
,
1
);
add_pat_entry
(
ts
,
sid
);
add_pid_to_pmt
(
ts
,
sid
,
0
);
//add pat pid to program
add_pid_to_pmt
(
ts
,
sid
,
0
);
//
add pat pid to program
add_pid_to_pmt
(
ts
,
sid
,
pmt_pid
);
}
}
...
...
@@ -1579,7 +1627,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
hex_dump_debug
(
ts
->
stream
,
section
,
section_len
);
p_end
=
section
+
section_len
-
4
;
p
=
section
;
p
=
section
;
if
(
parse_section_header
(
h
,
&
p
,
p_end
)
<
0
)
return
;
if
(
h
->
tid
!=
SDT_TID
)
...
...
@@ -1590,7 +1638,7 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
val
=
get8
(
&
p
,
p_end
);
if
(
val
<
0
)
return
;
for
(;;)
{
for
(;;)
{
sid
=
get16
(
&
p
,
p_end
);
if
(
sid
<
0
)
break
;
...
...
@@ -1601,10 +1649,10 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
if
(
desc_list_len
<
0
)
break
;
desc_list_len
&=
0xfff
;
desc_list_end
=
p
+
desc_list_len
;
desc_list_end
=
p
+
desc_list_len
;
if
(
desc_list_end
>
p_end
)
break
;
for
(;;)
{
for
(;;)
{
desc_tag
=
get8
(
&
p
,
desc_list_end
);
if
(
desc_tag
<
0
)
break
;
...
...
@@ -1614,9 +1662,9 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
break
;
av_dlog
(
ts
->
stream
,
"tag: 0x%02x len=%d
\n
"
,
desc_tag
,
desc_len
);
desc_tag
,
desc_len
);
switch
(
desc_tag
)
{
switch
(
desc_tag
)
{
case
0x48
:
service_type
=
get8
(
&
p
,
p_end
);
if
(
service_type
<
0
)
...
...
@@ -1627,9 +1675,10 @@ static void sdt_cb(MpegTSFilter *filter, const uint8_t *section, int section_len
name
=
getstr8
(
&
p
,
p_end
);
if
(
name
)
{
AVProgram
*
program
=
av_new_program
(
ts
->
stream
,
sid
);
if
(
program
)
{
if
(
program
)
{
av_dict_set
(
&
program
->
metadata
,
"service_name"
,
name
,
0
);
av_dict_set
(
&
program
->
metadata
,
"service_provider"
,
provider_name
,
0
);
av_dict_set
(
&
program
->
metadata
,
"service_provider"
,
provider_name
,
0
);
}
}
av_free
(
name
);
...
...
@@ -1655,7 +1704,7 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
int64_t
pos
;
pid
=
AV_RB16
(
packet
+
1
)
&
0x1fff
;
if
(
pid
&&
discard_pid
(
ts
,
pid
))
if
(
pid
&&
discard_pid
(
ts
,
pid
))
return
0
;
is_start
=
packet
[
1
]
&
0x40
;
tss
=
ts
->
pids
[
pid
];
...
...
@@ -1669,26 +1718,26 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
afc
=
(
packet
[
3
]
>>
4
)
&
3
;
if
(
afc
==
0
)
/* reserved value */
return
0
;
has_adaptation
=
afc
&
2
;
has_payload
=
afc
&
1
;
is_discontinuity
=
has_adaptation
&&
packet
[
4
]
!=
0
/* with length > 0 */
&&
(
packet
[
5
]
&
0x80
);
/* and discontinuity indicated */
has_adaptation
=
afc
&
2
;
has_payload
=
afc
&
1
;
is_discontinuity
=
has_adaptation
&&
packet
[
4
]
!=
0
&&
/* with length > 0 */
(
packet
[
5
]
&
0x80
);
/* and discontinuity indicated */
/* continuity check (currently not used) */
cc
=
(
packet
[
3
]
&
0xf
);
expected_cc
=
has_payload
?
(
tss
->
last_cc
+
1
)
&
0x0f
:
tss
->
last_cc
;
cc_ok
=
pid
==
0x1FFF
// null packet PID
||
is_discontinuity
||
tss
->
last_cc
<
0
||
expected_cc
==
cc
;
cc_ok
=
pid
==
0x1FFF
||
// null packet PID
is_discontinuity
||
tss
->
last_cc
<
0
||
expected_cc
==
cc
;
tss
->
last_cc
=
cc
;
if
(
!
cc_ok
)
{
av_log
(
ts
->
stream
,
AV_LOG_WARNING
,
"Continuity check failed for pid %d expected %d got %d
\n
"
,
pid
,
expected_cc
,
cc
);
if
(
tss
->
type
==
MPEGTS_PES
)
{
if
(
tss
->
type
==
MPEGTS_PES
)
{
PESContext
*
pc
=
tss
->
u
.
pes_filter
.
opaque
;
pc
->
flags
|=
AV_PKT_FLAG_CORRUPT
;
}
...
...
@@ -1746,13 +1795,13 @@ static int handle_packet(MpegTSContext *ts, const uint8_t *packet)
}
/* XXX: try to find a better synchro over several packets (use
get_packet_size() ?) */
*
get_packet_size() ?) */
static
int
mpegts_resync
(
AVFormatContext
*
s
)
{
AVIOContext
*
pb
=
s
->
pb
;
int
c
,
i
;
for
(
i
=
0
;
i
<
MAX_RESYNC_SIZE
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_RESYNC_SIZE
;
i
++
)
{
c
=
avio_r8
(
pb
);
if
(
pb
->
eof_reached
)
return
-
1
;
...
...
@@ -1761,18 +1810,20 @@ static int mpegts_resync(AVFormatContext *s)
return
0
;
}
}
av_log
(
s
,
AV_LOG_ERROR
,
"max resync size reached, could not find sync byte
\n
"
);
av_log
(
s
,
AV_LOG_ERROR
,
"max resync size reached, could not find sync byte
\n
"
);
/* no sync found */
return
-
1
;
}
/* return -1 if error or EOF. Return 0 if OK. */
static
int
read_packet
(
AVFormatContext
*
s
,
uint8_t
*
buf
,
int
raw_packet_size
,
const
uint8_t
**
data
)
static
int
read_packet
(
AVFormatContext
*
s
,
uint8_t
*
buf
,
int
raw_packet_size
,
const
uint8_t
**
data
)
{
AVIOContext
*
pb
=
s
->
pb
;
int
len
;
for
(;;)
{
for
(;;)
{
len
=
ffio_read_indirect
(
pb
,
buf
,
TS_PACKET_SIZE
,
data
);
if
(
len
!=
TS_PACKET_SIZE
)
return
len
<
0
?
len
:
AVERROR_EOF
;
...
...
@@ -1802,7 +1853,7 @@ static void finished_reading_packet(AVFormatContext *s, int raw_packet_size)
static
int
handle_packets
(
MpegTSContext
*
ts
,
int
nb_packets
)
{
AVFormatContext
*
s
=
ts
->
stream
;
uint8_t
packet
[
TS_PACKET_SIZE
+
FF_INPUT_BUFFER_PADDING_SIZE
];
uint8_t
packet
[
TS_PACKET_SIZE
+
FF_INPUT_BUFFER_PADDING_SIZE
];
const
uint8_t
*
data
;
int
packet_num
,
ret
=
0
;
...
...
@@ -1813,10 +1864,10 @@ static int handle_packets(MpegTSContext *ts, int nb_packets)
for
(
i
=
0
;
i
<
NB_PID_MAX
;
i
++
)
{
if
(
ts
->
pids
[
i
])
{
if
(
ts
->
pids
[
i
]
->
type
==
MPEGTS_PES
)
{
PESContext
*
pes
=
ts
->
pids
[
i
]
->
u
.
pes_filter
.
opaque
;
av_buffer_unref
(
&
pes
->
buffer
);
pes
->
data_index
=
0
;
pes
->
state
=
MPEGTS_SKIP
;
/* skip until pes header */
PESContext
*
pes
=
ts
->
pids
[
i
]
->
u
.
pes_filter
.
opaque
;
av_buffer_unref
(
&
pes
->
buffer
);
pes
->
data_index
=
0
;
pes
->
state
=
MPEGTS_SKIP
;
/* skip until pes header */
}
ts
->
pids
[
i
]
->
last_cc
=
-
1
;
}
...
...
@@ -1826,8 +1877,8 @@ static int handle_packets(MpegTSContext *ts, int nb_packets)
ts
->
stop_parse
=
0
;
packet_num
=
0
;
memset
(
packet
+
TS_PACKET_SIZE
,
0
,
FF_INPUT_BUFFER_PADDING_SIZE
);
for
(;;)
{
if
(
ts
->
stop_parse
>
0
)
for
(;;)
{
if
(
ts
->
stop_parse
>
0
)
break
;
packet_num
++
;
if
(
nb_packets
!=
0
&&
packet_num
>=
nb_packets
)
...
...
@@ -1846,31 +1897,38 @@ static int handle_packets(MpegTSContext *ts, int nb_packets)
static
int
mpegts_probe
(
AVProbeData
*
p
)
{
const
int
size
=
p
->
buf_size
;
const
int
size
=
p
->
buf_size
;
int
score
,
fec_score
,
dvhs_score
;
int
check_count
=
size
/
TS_FEC_PACKET_SIZE
;
int
check_count
=
size
/
TS_FEC_PACKET_SIZE
;
#define CHECK_COUNT 10
if
(
check_count
<
CHECK_COUNT
)
return
-
1
;
score
=
analyze
(
p
->
buf
,
TS_PACKET_SIZE
*
check_count
,
TS_PACKET_SIZE
,
NULL
)
*
CHECK_COUNT
/
check_count
;
dvhs_score
=
analyze
(
p
->
buf
,
TS_DVHS_PACKET_SIZE
*
check_count
,
TS_DVHS_PACKET_SIZE
,
NULL
)
*
CHECK_COUNT
/
check_count
;
fec_score
=
analyze
(
p
->
buf
,
TS_FEC_PACKET_SIZE
*
check_count
,
TS_FEC_PACKET_SIZE
,
NULL
)
*
CHECK_COUNT
/
check_count
;
score
=
analyze
(
p
->
buf
,
TS_PACKET_SIZE
*
check_count
,
TS_PACKET_SIZE
,
NULL
)
*
CHECK_COUNT
/
check_count
;
dvhs_score
=
analyze
(
p
->
buf
,
TS_DVHS_PACKET_SIZE
*
check_count
,
TS_DVHS_PACKET_SIZE
,
NULL
)
*
CHECK_COUNT
/
check_count
;
fec_score
=
analyze
(
p
->
buf
,
TS_FEC_PACKET_SIZE
*
check_count
,
TS_FEC_PACKET_SIZE
,
NULL
)
*
CHECK_COUNT
/
check_count
;
av_dlog
(
NULL
,
"score: %d, dvhs_score: %d, fec_score: %d
\n
"
,
score
,
dvhs_score
,
fec_score
);
// we need a clear definition for the returned score otherwise things will become messy sooner or later
if
(
score
>
fec_score
&&
score
>
dvhs_score
&&
score
>
6
)
return
AVPROBE_SCORE_MAX
+
score
-
CHECK_COUNT
;
else
if
(
dvhs_score
>
score
&&
dvhs_score
>
fec_score
&&
dvhs_score
>
6
)
return
AVPROBE_SCORE_MAX
+
dvhs_score
-
CHECK_COUNT
;
else
if
(
fec_score
>
6
)
return
AVPROBE_SCORE_MAX
+
fec_score
-
CHECK_COUNT
;
else
return
-
1
;
/* we need a clear definition for the returned score otherwise
* things will become messy sooner or later */
if
(
score
>
fec_score
&&
score
>
dvhs_score
&&
score
>
6
)
return
AVPROBE_SCORE_MAX
+
score
-
CHECK_COUNT
;
else
if
(
dvhs_score
>
score
&&
dvhs_score
>
fec_score
&&
dvhs_score
>
6
)
return
AVPROBE_SCORE_MAX
+
dvhs_score
-
CHECK_COUNT
;
else
if
(
fec_score
>
6
)
return
AVPROBE_SCORE_MAX
+
fec_score
-
CHECK_COUNT
;
else
return
-
1
;
}
/* return the 90kHz PCR and the extension for the 27MHz PCR. return
(-1) if not available */
static
int
parse_pcr
(
int64_t
*
ppcr_high
,
int
*
ppcr_low
,
const
uint8_t
*
packet
)
* (-1) if not available */
static
int
parse_pcr
(
int64_t
*
ppcr_high
,
int
*
ppcr_low
,
const
uint8_t
*
packet
)
{
int
afc
,
len
,
flags
;
const
uint8_t
*
p
;
...
...
@@ -1879,7 +1937,7 @@ static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
afc
=
(
packet
[
3
]
>>
4
)
&
3
;
if
(
afc
<=
1
)
return
-
1
;
p
=
packet
+
4
;
p
=
packet
+
4
;
len
=
p
[
0
];
p
++
;
if
(
len
==
0
)
...
...
@@ -1890,17 +1948,17 @@ static int parse_pcr(int64_t *ppcr_high, int *ppcr_low,
return
-
1
;
if
(
len
<
6
)
return
-
1
;
v
=
AV_RB32
(
p
);
*
ppcr_high
=
((
int64_t
)
v
<<
1
)
|
(
p
[
4
]
>>
7
);
*
ppcr_low
=
((
p
[
4
]
&
1
)
<<
8
)
|
p
[
5
];
v
=
AV_RB32
(
p
);
*
ppcr_high
=
((
int64_t
)
v
<<
1
)
|
(
p
[
4
]
>>
7
);
*
ppcr_low
=
((
p
[
4
]
&
1
)
<<
8
)
|
p
[
5
];
return
0
;
}
static
int
mpegts_read_header
(
AVFormatContext
*
s
)
{
MpegTSContext
*
ts
=
s
->
priv_data
;
AVIOContext
*
pb
=
s
->
pb
;
uint8_t
buf
[
5
*
1024
];
AVIOContext
*
pb
=
s
->
pb
;
uint8_t
buf
[
5
*
1024
];
int
len
;
int64_t
pos
;
...
...
@@ -1912,7 +1970,7 @@ static int mpegts_read_header(AVFormatContext *s)
ts
->
raw_packet_size
=
get_packet_size
(
buf
,
sizeof
(
buf
));
if
(
ts
->
raw_packet_size
<=
0
)
goto
fail
;
ts
->
stream
=
s
;
ts
->
stream
=
s
;
ts
->
auto_guess
=
0
;
if
(
s
->
iformat
==
&
ff_mpegts_demuxer
)
{
...
...
@@ -1949,13 +2007,13 @@ static int mpegts_read_header(AVFormatContext *s)
goto
fail
;
avpriv_set_pts_info
(
st
,
60
,
1
,
27000000
);
st
->
codec
->
codec_type
=
AVMEDIA_TYPE_DATA
;
st
->
codec
->
codec_id
=
AV_CODEC_ID_MPEG2TS
;
st
->
codec
->
codec_id
=
AV_CODEC_ID_MPEG2TS
;
/* we iterate until we find two PCRs to estimate the bitrate */
pcr_pid
=
-
1
;
nb_pcrs
=
0
;
pcr_pid
=
-
1
;
nb_pcrs
=
0
;
nb_packets
=
0
;
for
(;;)
{
for
(;;)
{
ret
=
read_packet
(
s
,
packet
,
ts
->
raw_packet_size
,
&
data
);
if
(
ret
<
0
)
return
-
1
;
...
...
@@ -1978,24 +2036,23 @@ static int mpegts_read_header(AVFormatContext *s)
/* NOTE1: the bitrate is computed without the FEC */
/* NOTE2: it is only the bitrate of the start of the stream */
ts
->
pcr_incr
=
(
pcrs
[
1
]
-
pcrs
[
0
])
/
(
packet_count
[
1
]
-
packet_count
[
0
]);
ts
->
cur_pcr
=
pcrs
[
0
]
-
ts
->
pcr_incr
*
packet_count
[
0
];
s
->
bit_rate
=
(
TS_PACKET_SIZE
*
8
)
*
27e6
/
ts
->
pcr_incr
;
ts
->
cur_pcr
=
pcrs
[
0
]
-
ts
->
pcr_incr
*
packet_count
[
0
];
s
->
bit_rate
=
TS_PACKET_SIZE
*
8
*
27e6
/
ts
->
pcr_incr
;
st
->
codec
->
bit_rate
=
s
->
bit_rate
;
st
->
start_time
=
ts
->
cur_pcr
;
st
->
start_time
=
ts
->
cur_pcr
;
av_dlog
(
ts
->
stream
,
"start=%0.3f pcr=%0.3f incr=%d
\n
"
,
st
->
start_time
/
1000000
.
0
,
pcrs
[
0
]
/
27e6
,
ts
->
pcr_incr
);
}
avio_seek
(
pb
,
pos
,
SEEK_SET
);
return
0
;
fail:
fail:
return
-
1
;
}
#define MAX_PACKET_READAHEAD ((128 * 1024) / 188)
static
int
mpegts_raw_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
static
int
mpegts_raw_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
{
MpegTSContext
*
ts
=
s
->
priv_data
;
int
ret
,
i
;
...
...
@@ -2006,8 +2063,8 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
if
(
av_new_packet
(
pkt
,
TS_PACKET_SIZE
)
<
0
)
return
AVERROR
(
ENOMEM
);
pkt
->
pos
=
avio_tell
(
s
->
pb
);
ret
=
read_packet
(
s
,
pkt
->
data
,
ts
->
raw_packet_size
,
&
data
);
pkt
->
pos
=
avio_tell
(
s
->
pb
);
if
(
ret
<
0
)
{
av_free_packet
(
pkt
);
return
ret
;
...
...
@@ -2020,12 +2077,13 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
if
(
parse_pcr
(
&
pcr_h
,
&
pcr_l
,
pkt
->
data
)
==
0
)
{
/* we read the next PCR (XXX: optimize it by using a bigger buffer */
pos
=
avio_tell
(
s
->
pb
);
for
(
i
=
0
;
i
<
MAX_PACKET_READAHEAD
;
i
++
)
{
for
(
i
=
0
;
i
<
MAX_PACKET_READAHEAD
;
i
++
)
{
avio_seek
(
s
->
pb
,
pos
+
i
*
ts
->
raw_packet_size
,
SEEK_SET
);
avio_read
(
s
->
pb
,
pcr_buf
,
12
);
if
(
parse_pcr
(
&
next_pcr_h
,
&
next_pcr_l
,
pcr_buf
)
==
0
)
{
/* XXX: not precise enough */
ts
->
pcr_incr
=
((
next_pcr_h
-
pcr_h
)
*
300
+
(
next_pcr_l
-
pcr_l
))
/
ts
->
pcr_incr
=
((
next_pcr_h
-
pcr_h
)
*
300
+
(
next_pcr_l
-
pcr_l
))
/
(
i
+
1
);
break
;
}
...
...
@@ -2034,16 +2092,15 @@ static int mpegts_raw_read_packet(AVFormatContext *s,
/* no next PCR found: we use previous increment */
ts
->
cur_pcr
=
pcr_h
*
300
+
pcr_l
;
}
pkt
->
pts
=
ts
->
cur_pcr
;
pkt
->
pts
=
ts
->
cur_pcr
;
pkt
->
duration
=
ts
->
pcr_incr
;
ts
->
cur_pcr
+=
ts
->
pcr_incr
;
ts
->
cur_pcr
+=
ts
->
pcr_incr
;
}
pkt
->
stream_index
=
0
;
return
0
;
}
static
int
mpegts_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
static
int
mpegts_read_packet
(
AVFormatContext
*
s
,
AVPacket
*
pkt
)
{
MpegTSContext
*
ts
=
s
->
priv_data
;
int
ret
,
i
;
...
...
@@ -2053,7 +2110,7 @@ static int mpegts_read_packet(AVFormatContext *s,
ret
=
handle_packets
(
ts
,
0
);
if
(
ret
<
0
)
{
/* flush pes data left */
for
(
i
=
0
;
i
<
NB_PID_MAX
;
i
++
)
{
for
(
i
=
0
;
i
<
NB_PID_MAX
;
i
++
)
if
(
ts
->
pids
[
i
]
&&
ts
->
pids
[
i
]
->
type
==
MPEGTS_PES
)
{
PESContext
*
pes
=
ts
->
pids
[
i
]
->
u
.
pes_filter
.
opaque
;
if
(
pes
->
state
==
MPEGTS_PAYLOAD
&&
pes
->
data_index
>
0
)
{
...
...
@@ -2063,7 +2120,6 @@ static int mpegts_read_packet(AVFormatContext *s,
break
;
}
}
}
}
if
(
!
ret
&&
pkt
->
size
<
0
)
...
...
@@ -2077,8 +2133,9 @@ static void mpegts_free(MpegTSContext *ts)
clear_programs
(
ts
);
for
(
i
=
0
;
i
<
NB_PID_MAX
;
i
++
)
if
(
ts
->
pids
[
i
])
mpegts_close_filter
(
ts
,
ts
->
pids
[
i
]);
for
(
i
=
0
;
i
<
NB_PID_MAX
;
i
++
)
if
(
ts
->
pids
[
i
])
mpegts_close_filter
(
ts
,
ts
->
pids
[
i
]);
}
static
int
mpegts_read_close
(
AVFormatContext
*
s
)
...
...
@@ -2094,11 +2151,14 @@ static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
MpegTSContext
*
ts
=
s
->
priv_data
;
int64_t
pos
,
timestamp
;
uint8_t
buf
[
TS_PACKET_SIZE
];
int
pcr_l
,
pcr_pid
=
((
PESContext
*
)
s
->
streams
[
stream_index
]
->
priv_data
)
->
pcr_pid
;
const
int
find_next
=
1
;
pos
=
((
*
ppos
+
ts
->
raw_packet_size
-
1
-
ts
->
pos47
)
/
ts
->
raw_packet_size
)
*
ts
->
raw_packet_size
+
ts
->
pos47
;
int
pcr_l
,
pcr_pid
=
((
PESContext
*
)
s
->
streams
[
stream_index
]
->
priv_data
)
->
pcr_pid
;
const
int
find_next
=
1
;
pos
=
((
*
ppos
+
ts
->
raw_packet_size
-
1
-
ts
->
pos47
)
/
ts
->
raw_packet_size
)
*
ts
->
raw_packet_size
+
ts
->
pos47
;
if
(
find_next
)
{
for
(;;)
{
for
(;;)
{
avio_seek
(
s
->
pb
,
pos
,
SEEK_SET
);
if
(
avio_read
(
s
->
pb
,
buf
,
TS_PACKET_SIZE
)
!=
TS_PACKET_SIZE
)
return
AV_NOPTS_VALUE
;
...
...
@@ -2109,7 +2169,7 @@ static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
pos
+=
ts
->
raw_packet_size
;
}
}
else
{
for
(;;)
{
for
(;;)
{
pos
-=
ts
->
raw_packet_size
;
if
(
pos
<
0
)
return
AV_NOPTS_VALUE
;
...
...
@@ -2127,7 +2187,8 @@ static int64_t mpegts_get_pcr(AVFormatContext *s, int stream_index,
return
timestamp
;
}
static
int
read_seek
(
AVFormatContext
*
s
,
int
stream_index
,
int64_t
target_ts
,
int
flags
){
static
int
read_seek
(
AVFormatContext
*
s
,
int
stream_index
,
int64_t
target_ts
,
int
flags
)
{
MpegTSContext
*
ts
=
s
->
priv_data
;
uint8_t
buf
[
TS_PACKET_SIZE
];
int64_t
pos
;
...
...
@@ -2135,14 +2196,15 @@ static int read_seek(AVFormatContext *s, int stream_index, int64_t target_ts, in
if
(
ff_seek_frame_binary
(
s
,
stream_index
,
target_ts
,
flags
)
<
0
)
return
-
1
;
pos
=
avio_tell
(
s
->
pb
);
pos
=
avio_tell
(
s
->
pb
);
for
(;;)
{
for
(;;)
{
avio_seek
(
s
->
pb
,
pos
,
SEEK_SET
);
if
(
avio_read
(
s
->
pb
,
buf
,
TS_PACKET_SIZE
)
!=
TS_PACKET_SIZE
)
return
-
1
;
// pid = AV_RB16(buf + 1) & 0x1fff;
if
(
buf
[
1
]
&
0x40
)
break
;
// pid = AV_RB16(buf + 1) & 0x1fff;
if
(
buf
[
1
]
&
0x40
)
break
;
pos
+=
ts
->
raw_packet_size
;
}
avio_seek
(
s
->
pb
,
pos
,
SEEK_SET
);
...
...
@@ -2168,17 +2230,17 @@ MpegTSContext *ff_mpegts_parse_open(AVFormatContext *s)
}
/* return the consumed length if a packet was output, or -1 if no
packet is output */
*
packet is output */
int
ff_mpegts_parse_packet
(
MpegTSContext
*
ts
,
AVPacket
*
pkt
,
const
uint8_t
*
buf
,
int
len
)
const
uint8_t
*
buf
,
int
len
)
{
int
len1
;
len1
=
len
;
ts
->
pkt
=
pkt
;
ts
->
stop_parse
=
0
;
for
(;;)
{
if
(
ts
->
stop_parse
>
0
)
for
(;;)
{
if
(
ts
->
stop_parse
>
0
)
break
;
if
(
len
<
TS_PACKET_SIZE
)
return
-
1
;
...
...
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