Skip to content
Projects
Groups
Snippets
Help
Loading...
Sign in / Register
Toggle navigation
F
ffmpeg
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
Packages
Packages
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
submodule
ffmpeg
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