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
1565a9a9
Commit
1565a9a9
authored
Dec 05, 2013
by
Michael Niedermayer
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avformat/utils: factor rfps calculation out
Signed-off-by:
Michael Niedermayer
<
michaelni@gmx.at
>
parent
dc1b0a54
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
102 additions
and
67 deletions
+102
-67
internal.h
libavformat/internal.h
+10
-0
utils.c
libavformat/utils.c
+92
-67
No files found.
libavformat/internal.h
View file @
1565a9a9
...
...
@@ -371,4 +371,14 @@ int ff_generate_avci_extradata(AVStream *st);
*/
int
ff_alloc_extradata
(
AVCodecContext
*
avctx
,
int
size
);
/**
* add frame for rfps calculation.
*
* @param dts timestamp of the i-th frame
* @return 0 if OK, AVERROR_xxx on error
*/
int
ff_rfps_add_frame
(
AVFormatContext
*
ic
,
AVStream
*
st
,
int64_t
dts
);
void
ff_rfps_calculate
(
AVFormatContext
*
ic
);
#endif
/* AVFORMAT_INTERNAL_H */
libavformat/utils.c
View file @
1565a9a9
...
...
@@ -2701,6 +2701,94 @@ int ff_alloc_extradata(AVCodecContext *avctx, int size)
return
ret
;
}
int
ff_rfps_add_frame
(
AVFormatContext
*
ic
,
AVStream
*
st
,
int64_t
ts
)
{
int
i
,
j
;
int64_t
last
=
st
->
info
->
last_dts
;
if
(
ts
!=
AV_NOPTS_VALUE
&&
last
!=
AV_NOPTS_VALUE
&&
ts
>
last
&&
ts
-
(
uint64_t
)
last
<
INT64_MAX
){
double
dts
=
(
is_relative
(
ts
)
?
ts
-
RELATIVE_TS_BASE
:
ts
)
*
av_q2d
(
st
->
time_base
);
int64_t
duration
=
ts
-
last
;
if
(
!
st
->
info
->
duration_error
)
st
->
info
->
duration_error
=
av_mallocz
(
sizeof
(
st
->
info
->
duration_error
[
0
])
*
2
);
if
(
!
st
->
info
->
duration_error
)
return
AVERROR
(
ENOMEM
);
// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
for
(
i
=
0
;
i
<
MAX_STD_TIMEBASES
;
i
++
)
{
int
framerate
=
get_std_framerate
(
i
);
double
sdts
=
dts
*
framerate
/
(
1001
*
12
);
for
(
j
=
0
;
j
<
2
;
j
++
){
int64_t
ticks
=
llrint
(
sdts
+
j
*
0
.
5
);
double
error
=
sdts
-
ticks
+
j
*
0
.
5
;
st
->
info
->
duration_error
[
j
][
0
][
i
]
+=
error
;
st
->
info
->
duration_error
[
j
][
1
][
i
]
+=
error
*
error
;
}
}
st
->
info
->
duration_count
++
;
// ignore the first 4 values, they might have some random jitter
if
(
st
->
info
->
duration_count
>
3
&&
is_relative
(
ts
)
==
is_relative
(
last
))
st
->
info
->
duration_gcd
=
av_gcd
(
st
->
info
->
duration_gcd
,
duration
);
}
if
(
ts
!=
AV_NOPTS_VALUE
)
st
->
info
->
last_dts
=
ts
;
return
0
;
}
void
ff_rfps_calculate
(
AVFormatContext
*
ic
)
{
int
i
,
j
;
for
(
i
=
0
;
i
<
ic
->
nb_streams
;
i
++
)
{
AVStream
*
st
=
ic
->
streams
[
i
];
if
(
st
->
codec
->
codec_type
!=
AVMEDIA_TYPE_VIDEO
)
continue
;
// the check for tb_unreliable() is not completely correct, since this is not about handling
// a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
// ipmovie.c produces.
if
(
tb_unreliable
(
st
->
codec
)
&&
st
->
info
->
duration_count
>
15
&&
st
->
info
->
duration_gcd
>
FFMAX
(
1
,
st
->
time_base
.
den
/
(
500LL
*
st
->
time_base
.
num
))
&&
!
st
->
r_frame_rate
.
num
)
av_reduce
(
&
st
->
r_frame_rate
.
num
,
&
st
->
r_frame_rate
.
den
,
st
->
time_base
.
den
,
st
->
time_base
.
num
*
st
->
info
->
duration_gcd
,
INT_MAX
);
if
(
st
->
info
->
duration_count
>
1
&&
!
st
->
r_frame_rate
.
num
&&
tb_unreliable
(
st
->
codec
))
{
int
num
=
0
;
double
best_error
=
0
.
01
;
for
(
j
=
0
;
j
<
MAX_STD_TIMEBASES
;
j
++
)
{
int
k
;
if
(
st
->
info
->
codec_info_duration
&&
st
->
info
->
codec_info_duration
*
av_q2d
(
st
->
time_base
)
<
(
1001
*
12
.
0
)
/
get_std_framerate
(
j
))
continue
;
if
(
!
st
->
info
->
codec_info_duration
&&
1
.
0
<
(
1001
*
12
.
0
)
/
get_std_framerate
(
j
))
continue
;
for
(
k
=
0
;
k
<
2
;
k
++
){
int
n
=
st
->
info
->
duration_count
;
double
a
=
st
->
info
->
duration_error
[
k
][
0
][
j
]
/
n
;
double
error
=
st
->
info
->
duration_error
[
k
][
1
][
j
]
/
n
-
a
*
a
;
if
(
error
<
best_error
&&
best_error
>
0
.
000000001
){
best_error
=
error
;
num
=
get_std_framerate
(
j
);
}
if
(
error
<
0
.
02
)
av_log
(
NULL
,
AV_LOG_DEBUG
,
"rfps: %f %f
\n
"
,
get_std_framerate
(
j
)
/
12
.
0
/
1001
,
error
);
}
}
// do not increase frame rate by more than 1 % in order to match a standard rate.
if
(
num
&&
(
!
st
->
r_frame_rate
.
num
||
(
double
)
num
/
(
12
*
1001
)
<
1
.
01
*
av_q2d
(
st
->
r_frame_rate
)))
av_reduce
(
&
st
->
r_frame_rate
.
num
,
&
st
->
r_frame_rate
.
den
,
num
,
12
*
1001
,
INT_MAX
);
}
av_freep
(
&
st
->
info
->
duration_error
);
st
->
info
->
last_dts
=
AV_NOPTS_VALUE
;
st
->
info
->
duration_count
=
0
;
}
}
int
avformat_find_stream_info
(
AVFormatContext
*
ic
,
AVDictionary
**
options
)
{
int
i
,
count
,
ret
=
0
,
j
;
...
...
@@ -2918,39 +3006,7 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
}
}
#if FF_API_R_FRAME_RATE
{
int64_t
last
=
st
->
info
->
last_dts
;
if
(
pkt
->
dts
!=
AV_NOPTS_VALUE
&&
last
!=
AV_NOPTS_VALUE
&&
pkt
->
dts
>
last
&&
pkt
->
dts
-
(
uint64_t
)
last
<
INT64_MAX
){
double
dts
=
(
is_relative
(
pkt
->
dts
)
?
pkt
->
dts
-
RELATIVE_TS_BASE
:
pkt
->
dts
)
*
av_q2d
(
st
->
time_base
);
int64_t
duration
=
pkt
->
dts
-
last
;
if
(
!
st
->
info
->
duration_error
)
st
->
info
->
duration_error
=
av_mallocz
(
sizeof
(
st
->
info
->
duration_error
[
0
])
*
2
);
if
(
!
st
->
info
->
duration_error
)
return
AVERROR
(
ENOMEM
);
// if(st->codec->codec_type == AVMEDIA_TYPE_VIDEO)
// av_log(NULL, AV_LOG_ERROR, "%f\n", dts);
for
(
i
=
0
;
i
<
MAX_STD_TIMEBASES
;
i
++
)
{
int
framerate
=
get_std_framerate
(
i
);
double
sdts
=
dts
*
framerate
/
(
1001
*
12
);
for
(
j
=
0
;
j
<
2
;
j
++
){
int64_t
ticks
=
llrint
(
sdts
+
j
*
0
.
5
);
double
error
=
sdts
-
ticks
+
j
*
0
.
5
;
st
->
info
->
duration_error
[
j
][
0
][
i
]
+=
error
;
st
->
info
->
duration_error
[
j
][
1
][
i
]
+=
error
*
error
;
}
}
st
->
info
->
duration_count
++
;
// ignore the first 4 values, they might have some random jitter
if
(
st
->
info
->
duration_count
>
3
&&
is_relative
(
pkt
->
dts
)
==
is_relative
(
last
))
st
->
info
->
duration_gcd
=
av_gcd
(
st
->
info
->
duration_gcd
,
duration
);
}
if
(
pkt
->
dts
!=
AV_NOPTS_VALUE
)
st
->
info
->
last_dts
=
pkt
->
dts
;
}
ff_rfps_add_frame
(
ic
,
st
,
pkt
->
dts
);
#endif
if
(
st
->
parser
&&
st
->
parser
->
parser
->
split
&&
!
st
->
codec
->
extradata
){
int
i
=
st
->
parser
->
parser
->
split
(
st
->
codec
,
pkt
->
data
,
pkt
->
size
);
...
...
@@ -3006,6 +3062,9 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
st
=
ic
->
streams
[
i
];
avcodec_close
(
st
->
codec
);
}
ff_rfps_calculate
(
ic
);
for
(
i
=
0
;
i
<
ic
->
nb_streams
;
i
++
)
{
st
=
ic
->
streams
[
i
];
if
(
st
->
codec
->
codec_type
==
AVMEDIA_TYPE_VIDEO
)
{
...
...
@@ -3044,40 +3103,6 @@ int avformat_find_stream_info(AVFormatContext *ic, AVDictionary **options)
best_fps
,
12
*
1001
,
INT_MAX
);
}
}
// the check for tb_unreliable() is not completely correct, since this is not about handling
// a unreliable/inexact time base, but a time base that is finer than necessary, as e.g.
// ipmovie.c produces.
if
(
tb_unreliable
(
st
->
codec
)
&&
st
->
info
->
duration_count
>
15
&&
st
->
info
->
duration_gcd
>
FFMAX
(
1
,
st
->
time_base
.
den
/
(
500LL
*
st
->
time_base
.
num
))
&&
!
st
->
r_frame_rate
.
num
)
av_reduce
(
&
st
->
r_frame_rate
.
num
,
&
st
->
r_frame_rate
.
den
,
st
->
time_base
.
den
,
st
->
time_base
.
num
*
st
->
info
->
duration_gcd
,
INT_MAX
);
if
(
st
->
info
->
duration_count
>
1
&&
!
st
->
r_frame_rate
.
num
&&
tb_unreliable
(
st
->
codec
))
{
int
num
=
0
;
double
best_error
=
0
.
01
;
for
(
j
=
0
;
j
<
MAX_STD_TIMEBASES
;
j
++
)
{
int
k
;
if
(
st
->
info
->
codec_info_duration
&&
st
->
info
->
codec_info_duration
*
av_q2d
(
st
->
time_base
)
<
(
1001
*
12
.
0
)
/
get_std_framerate
(
j
))
continue
;
if
(
!
st
->
info
->
codec_info_duration
&&
1
.
0
<
(
1001
*
12
.
0
)
/
get_std_framerate
(
j
))
continue
;
for
(
k
=
0
;
k
<
2
;
k
++
){
int
n
=
st
->
info
->
duration_count
;
double
a
=
st
->
info
->
duration_error
[
k
][
0
][
j
]
/
n
;
double
error
=
st
->
info
->
duration_error
[
k
][
1
][
j
]
/
n
-
a
*
a
;
if
(
error
<
best_error
&&
best_error
>
0
.
000000001
){
best_error
=
error
;
num
=
get_std_framerate
(
j
);
}
if
(
error
<
0
.
02
)
av_log
(
NULL
,
AV_LOG_DEBUG
,
"rfps: %f %f
\n
"
,
get_std_framerate
(
j
)
/
12
.
0
/
1001
,
error
);
}
}
// do not increase frame rate by more than 1 % in order to match a standard rate.
if
(
num
&&
(
!
st
->
r_frame_rate
.
num
||
(
double
)
num
/
(
12
*
1001
)
<
1
.
01
*
av_q2d
(
st
->
r_frame_rate
)))
av_reduce
(
&
st
->
r_frame_rate
.
num
,
&
st
->
r_frame_rate
.
den
,
num
,
12
*
1001
,
INT_MAX
);
}
if
(
!
st
->
r_frame_rate
.
num
){
if
(
st
->
codec
->
time_base
.
den
*
(
int64_t
)
st
->
time_base
.
num
...
...
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