Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
ffmpeg
Project
Project
Details
Activity
Releases
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
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Stefan Westerfeld
ffmpeg
Commits
278984b3
Commit
278984b3
authored
Nov 24, 2020
by
Paul B Mahol
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
avfilter/vf_readeia608: add support for slice threads
parent
97bc6900
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
161 additions
and
75 deletions
+161
-75
vf_readeia608.c
libavfilter/vf_readeia608.c
+161
-75
No files found.
libavfilter/vf_readeia608.c
View file @
278984b3
...
...
@@ -57,20 +57,28 @@ typedef struct CodeItem {
int
size
;
}
CodeItem
;
typedef
struct
ScanItem
{
int
nb_line
;
int
found
;
int
white
;
int
black
;
uint64_t
histogram
[
256
];
uint8_t
byte
[
2
];
CodeItem
*
code
;
LineItem
*
line
;
}
ScanItem
;
typedef
struct
ReadEIA608Context
{
const
AVClass
*
class
;
int
start
,
end
;
int
nb_found
;
int
white
;
int
black
;
float
spw
;
int
chp
;
int
lp
;
uint64_t
histogram
[
256
];
CodeItem
*
code
;
LineItem
*
line
;
int
nb_allocated
;
ScanItem
*
scan
;
}
ReadEIA608Context
;
#define OFFSET(x) offsetof(ReadEIA608Context, x)
...
...
@@ -105,53 +113,80 @@ static int query_formats(AVFilterContext *ctx)
return
ff_set_common_formats
(
ctx
,
formats
);
}
static
int
config_
input
(
AVFilterLink
*
inlink
)
static
int
config_
filter
(
AVFilterContext
*
ctx
,
int
start
,
int
end
)
{
AVFilterContext
*
ctx
=
inlink
->
dst
;
ReadEIA608Context
*
s
=
ctx
->
priv
;
AVFilterLink
*
inlink
=
ctx
->
inputs
[
0
];
int
size
=
inlink
->
w
+
LAG
;
if
(
s
->
end
>=
inlink
->
h
)
{
if
(
end
>=
inlink
->
h
)
{
av_log
(
ctx
,
AV_LOG_WARNING
,
"Last line to scan too large, clipping.
\n
"
);
s
->
end
=
inlink
->
h
-
1
;
end
=
inlink
->
h
-
1
;
}
if
(
s
->
start
>
s
->
end
)
{
if
(
s
tart
>
end
)
{
av_log
(
ctx
,
AV_LOG_ERROR
,
"Invalid range.
\n
"
);
return
AVERROR
(
EINVAL
);
}
s
->
line
=
av_calloc
(
size
,
sizeof
(
*
s
->
line
));
s
->
code
=
av_calloc
(
size
,
sizeof
(
*
s
->
code
));
if
(
!
s
->
line
||
!
s
->
code
)
return
AVERROR
(
ENOMEM
);
if
(
s
->
nb_allocated
<
end
-
start
+
1
)
{
const
int
diff
=
end
-
start
+
1
-
s
->
nb_allocated
;
s
->
scan
=
av_realloc_f
(
s
->
scan
,
end
-
start
+
1
,
sizeof
(
*
s
->
scan
));
if
(
!
s
->
scan
)
return
AVERROR
(
ENOMEM
);
memset
(
&
s
->
scan
[
s
->
nb_allocated
],
0
,
diff
*
sizeof
(
*
s
->
scan
));
s
->
nb_allocated
=
end
-
start
+
1
;
}
for
(
int
i
=
0
;
i
<
s
->
nb_allocated
;
i
++
)
{
ScanItem
*
scan
=
&
s
->
scan
[
i
];
if
(
!
scan
->
line
)
scan
->
line
=
av_calloc
(
size
,
sizeof
(
*
scan
->
line
));
if
(
!
scan
->
code
)
scan
->
code
=
av_calloc
(
size
,
sizeof
(
*
scan
->
code
));
if
(
!
scan
->
line
||
!
scan
->
code
)
return
AVERROR
(
ENOMEM
);
}
s
->
start
=
start
;
s
->
end
=
end
;
return
0
;
}
static
void
build_histogram
(
ReadEIA608Context
*
s
,
const
LineItem
*
line
,
int
len
)
static
int
config_input
(
AVFilterLink
*
inlink
)
{
memset
(
s
->
histogram
,
0
,
sizeof
(
s
->
histogram
));
AVFilterContext
*
ctx
=
inlink
->
dst
;
ReadEIA608Context
*
s
=
ctx
->
priv
;
return
config_filter
(
ctx
,
s
->
start
,
s
->
end
);
}
static
void
build_histogram
(
ReadEIA608Context
*
s
,
ScanItem
*
scan
,
const
LineItem
*
line
,
int
len
)
{
memset
(
scan
->
histogram
,
0
,
sizeof
(
scan
->
histogram
));
for
(
int
i
=
LAG
;
i
<
len
+
LAG
;
i
++
)
s
->
histogram
[
line
[
i
].
input
]
++
;
s
can
->
histogram
[
line
[
i
].
input
]
++
;
}
static
void
find_black_and_white
(
ReadEIA608Context
*
s
)
static
void
find_black_and_white
(
ReadEIA608Context
*
s
,
ScanItem
*
scan
)
{
int
start
=
0
,
end
=
0
,
middle
;
int
black
=
0
,
white
=
0
;
int
cnt
;
for
(
int
i
=
0
;
i
<
256
;
i
++
)
{
if
(
s
->
histogram
[
i
])
{
if
(
s
can
->
histogram
[
i
])
{
start
=
i
;
break
;
}
}
for
(
int
i
=
255
;
i
>=
0
;
i
--
)
{
if
(
s
->
histogram
[
i
])
{
if
(
s
can
->
histogram
[
i
])
{
end
=
i
;
break
;
}
...
...
@@ -161,22 +196,22 @@ static void find_black_and_white(ReadEIA608Context *s)
cnt
=
0
;
for
(
int
i
=
start
;
i
<=
middle
;
i
++
)
{
if
(
s
->
histogram
[
i
]
>
cnt
)
{
cnt
=
s
->
histogram
[
i
];
if
(
s
can
->
histogram
[
i
]
>
cnt
)
{
cnt
=
s
can
->
histogram
[
i
];
black
=
i
;
}
}
cnt
=
0
;
for
(
int
i
=
end
;
i
>=
middle
;
i
--
)
{
if
(
s
->
histogram
[
i
]
>
cnt
)
{
cnt
=
s
->
histogram
[
i
];
if
(
s
can
->
histogram
[
i
]
>
cnt
)
{
cnt
=
s
can
->
histogram
[
i
];
white
=
i
;
}
}
s
->
black
=
black
;
s
->
white
=
white
;
s
can
->
black
=
black
;
s
can
->
white
=
white
;
}
static
float
meanf
(
const
LineItem
*
line
,
int
len
)
...
...
@@ -202,7 +237,7 @@ static float stddevf(const LineItem *line, int len)
return
sqrtf
(
standard_deviation
/
(
len
-
1
));
}
static
void
thresholding
(
ReadEIA608Context
*
s
,
LineItem
*
line
,
static
void
thresholding
(
ReadEIA608Context
*
s
,
ScanItem
*
scan
,
LineItem
*
line
,
int
lag
,
float
threshold
,
float
influence
,
int
len
)
{
for
(
int
i
=
lag
;
i
<
len
+
lag
;
i
++
)
{
...
...
@@ -230,8 +265,8 @@ static void thresholding(ReadEIA608Context *s, LineItem *line,
}
else
{
int
distance_from_black
,
distance_from_white
;
distance_from_black
=
FFABS
(
line
[
i
].
input
-
s
->
black
);
distance_from_white
=
FFABS
(
line
[
i
].
input
-
s
->
white
);
distance_from_black
=
FFABS
(
line
[
i
].
input
-
s
can
->
black
);
distance_from_white
=
FFABS
(
line
[
i
].
input
-
s
can
->
white
);
line
[
i
].
output
=
distance_from_black
<=
distance_from_white
?
0
:
255
;
}
...
...
@@ -264,29 +299,28 @@ static int periods(const LineItem *line, CodeItem *code, int len)
return
cnt
+
1
;
}
static
void
dump_code
(
AVFilterContext
*
ctx
,
int
len
,
int
item
)
static
void
dump_code
(
AVFilterContext
*
ctx
,
ScanItem
*
scan
,
int
len
,
int
item
)
{
ReadEIA608Context
*
s
=
ctx
->
priv
;
av_log
(
ctx
,
AV_LOG_DEBUG
,
"%d:"
,
item
);
for
(
int
i
=
0
;
i
<
len
;
i
++
)
{
av_log
(
ctx
,
AV_LOG_DEBUG
,
" %03d"
,
s
->
code
[
i
].
size
);
av_log
(
ctx
,
AV_LOG_DEBUG
,
" %03d"
,
s
can
->
code
[
i
].
size
);
}
av_log
(
ctx
,
AV_LOG_DEBUG
,
"
\n
"
);
}
static
void
extract_line
(
AVFilterContext
*
ctx
,
AVFrame
*
in
,
int
w
,
int
nb_line
)
static
void
extract_line
(
AVFilterContext
*
ctx
,
AVFrame
*
in
,
ScanItem
*
scan
,
int
w
,
int
nb_line
)
{
ReadEIA608Context
*
s
=
ctx
->
priv
;
LineItem
*
line
=
s
->
line
;
LineItem
*
line
=
s
can
->
line
;
int
i
,
j
,
ch
,
len
;
const
uint8_t
*
src
;
uint8_t
byte
[
2
]
=
{
0
};
uint8_t
codes
[
19
]
=
{
0
};
float
bit_size
=
0
.
f
;
int
parity
;
memset
(
line
,
0
,
(
w
+
LAG
)
*
sizeof
(
*
line
));
scan
->
byte
[
0
]
=
scan
->
byte
[
1
]
=
0
;
scan
->
found
=
0
;
src
=
&
in
->
data
[
0
][
nb_line
*
in
->
linesize
[
0
]];
if
(
s
->
lp
)
{
...
...
@@ -306,42 +340,42 @@ static void extract_line(AVFilterContext *ctx, AVFrame *in, int w, int nb_line)
}
}
build_histogram
(
s
,
line
,
w
);
find_black_and_white
(
s
);
if
(
s
->
white
-
s
->
black
<
5
)
build_histogram
(
s
,
scan
,
line
,
w
);
find_black_and_white
(
s
,
scan
);
if
(
s
can
->
white
-
scan
->
black
<
5
)
return
;
thresholding
(
s
,
line
,
LAG
,
1
,
0
,
w
);
len
=
periods
(
line
,
s
->
code
,
w
);
dump_code
(
ctx
,
len
,
nb_line
);
thresholding
(
s
,
scan
,
line
,
LAG
,
1
,
0
,
w
);
len
=
periods
(
line
,
s
can
->
code
,
w
);
dump_code
(
ctx
,
scan
,
len
,
nb_line
);
if
(
len
<
15
||
s
->
code
[
14
].
bit
!=
0
||
w
/
(
float
)
s
->
code
[
14
].
size
<
SYNC_BITSIZE_MIN
||
w
/
(
float
)
s
->
code
[
14
].
size
>
SYNC_BITSIZE_MAX
)
{
s
can
->
code
[
14
].
bit
!=
0
||
w
/
(
float
)
s
can
->
code
[
14
].
size
<
SYNC_BITSIZE_MIN
||
w
/
(
float
)
s
can
->
code
[
14
].
size
>
SYNC_BITSIZE_MAX
)
{
return
;
}
for
(
i
=
14
;
i
<
len
;
i
++
)
{
bit_size
+=
s
->
code
[
i
].
size
;
bit_size
+=
s
can
->
code
[
i
].
size
;
}
bit_size
/=
19
.
f
;
for
(
i
=
1
;
i
<
14
;
i
++
)
{
if
(
s
->
code
[
i
].
size
/
bit_size
>
CLOCK_BITSIZE_MAX
||
s
->
code
[
i
].
size
/
bit_size
<
CLOCK_BITSIZE_MIN
)
{
if
(
s
can
->
code
[
i
].
size
/
bit_size
>
CLOCK_BITSIZE_MAX
||
s
can
->
code
[
i
].
size
/
bit_size
<
CLOCK_BITSIZE_MIN
)
{
return
;
}
}
if
(
s
->
code
[
15
].
size
/
bit_size
<
0
.
45
f
)
{
if
(
s
can
->
code
[
15
].
size
/
bit_size
<
0
.
45
f
)
{
return
;
}
for
(
j
=
0
,
i
=
14
;
i
<
len
;
i
++
)
{
int
run
,
bit
;
run
=
lrintf
(
s
->
code
[
i
].
size
/
bit_size
);
bit
=
s
->
code
[
i
].
bit
;
run
=
lrintf
(
s
can
->
code
[
i
].
size
/
bit_size
);
bit
=
s
can
->
code
[
i
].
bit
;
for
(
int
k
=
0
;
j
<
19
&&
k
<
run
;
k
++
)
{
codes
[
j
++
]
=
bit
;
...
...
@@ -361,33 +395,37 @@ static void extract_line(AVFilterContext *ctx, AVFrame *in, int w, int nb_line)
}
else
{
b
=
0
;
}
byte
[
ch
]
|=
b
<<
i
;
scan
->
byte
[
ch
]
|=
b
<<
i
;
}
if
(
s
->
chp
)
{
if
(
!
(
parity
&
1
))
{
byte
[
ch
]
=
0x7F
;
scan
->
byte
[
ch
]
=
0x7F
;
}
}
}
{
uint8_t
key
[
128
],
value
[
128
];
scan
->
nb_line
=
nb_line
;
scan
->
found
=
1
;
}
//snprintf(key, sizeof(key), "lavfi.readeia608.%d.bits", s->nb_found);
//snprintf(value, sizeof(value), "0b%d%d%d%d%d%d%d%d 0b%d%d%d%d%d%d%d%d", codes[3]==255,codes[4]==255,codes[5]==255,codes[6]==255,codes[7]==255,codes[8]==255,codes[9]==255,codes[10]==255,codes[11]==255,codes[12]==255,codes[13]==255,codes[14]==255,codes[15]==255,codes[16]==255,codes[17]==255,codes[18]==255);
//av_dict_set(&in->metadata, key, value, 0);
static
int
extract_lines
(
AVFilterContext
*
ctx
,
void
*
arg
,
int
job
,
int
nb_jobs
)
{
ReadEIA608Context
*
s
=
ctx
->
priv
;
AVFilterLink
*
inlink
=
ctx
->
inputs
[
0
];
const
int
h
=
s
->
end
-
s
->
start
+
1
;
const
int
start
=
(
h
*
job
)
/
nb_jobs
;
const
int
end
=
(
h
*
(
job
+
1
))
/
nb_jobs
;
AVFrame
*
in
=
arg
;
snprintf
(
key
,
sizeof
(
key
),
"lavfi.readeia608.%d.cc"
,
s
->
nb_found
);
snprintf
(
value
,
sizeof
(
value
),
"0x%02X%02X"
,
byte
[
0
],
byte
[
1
]);
av_dict_set
(
&
in
->
metadata
,
key
,
value
,
0
);
for
(
int
i
=
start
;
i
<
end
;
i
++
)
{
ScanItem
*
scan
=
&
s
->
scan
[
i
];
snprintf
(
key
,
sizeof
(
key
),
"lavfi.readeia608.%d.line"
,
s
->
nb_found
);
snprintf
(
value
,
sizeof
(
value
),
"%d"
,
nb_line
);
av_dict_set
(
&
in
->
metadata
,
key
,
value
,
0
);
extract_line
(
ctx
,
in
,
scan
,
inlink
->
w
,
i
);
}
s
->
nb_found
++
;
return
0
;
}
static
int
filter_frame
(
AVFilterLink
*
inlink
,
AVFrame
*
in
)
...
...
@@ -395,11 +433,33 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *in)
AVFilterContext
*
ctx
=
inlink
->
dst
;
AVFilterLink
*
outlink
=
ctx
->
outputs
[
0
];
ReadEIA608Context
*
s
=
ctx
->
priv
;
int
i
;
int
nb_found
;
ctx
->
internal
->
execute
(
ctx
,
extract_lines
,
in
,
NULL
,
FFMIN
(
FFMAX
(
s
->
end
-
s
->
start
+
1
,
1
),
ff_filter_get_nb_threads
(
ctx
)));
nb_found
=
0
;
for
(
int
i
=
0
;
i
<
s
->
end
-
s
->
start
+
1
;
i
++
)
{
ScanItem
*
scan
=
&
s
->
scan
[
i
];
uint8_t
key
[
128
],
value
[
128
];
if
(
!
scan
->
found
)
continue
;
//snprintf(key, sizeof(key), "lavfi.readeia608.%d.bits", nb_found);
//snprintf(value, sizeof(value), "0b%d%d%d%d%d%d%d%d 0b%d%d%d%d%d%d%d%d", codes[3]==255,codes[4]==255,codes[5]==255,codes[6]==255,codes[7]==255,codes[8]==255,codes[9]==255,codes[10]==255,codes[11]==255,codes[12]==255,codes[13]==255,codes[14]==255,codes[15]==255,codes[16]==255,codes[17]==255,codes[18]==255);
//av_dict_set(&in->metadata, key, value, 0);
s
->
nb_found
=
0
;
for
(
i
=
s
->
start
;
i
<=
s
->
end
;
i
++
)
extract_line
(
ctx
,
in
,
inlink
->
w
,
i
);
snprintf
(
key
,
sizeof
(
key
),
"lavfi.readeia608.%d.cc"
,
nb_found
);
snprintf
(
value
,
sizeof
(
value
),
"0x%02X%02X"
,
scan
->
byte
[
0
],
scan
->
byte
[
1
]);
av_dict_set
(
&
in
->
metadata
,
key
,
value
,
0
);
snprintf
(
key
,
sizeof
(
key
),
"lavfi.readeia608.%d.line"
,
nb_found
);
snprintf
(
value
,
sizeof
(
value
),
"%d"
,
scan
->
nb_line
);
av_dict_set
(
&
in
->
metadata
,
key
,
value
,
0
);
nb_found
++
;
}
return
ff_filter_frame
(
outlink
,
in
);
}
...
...
@@ -408,8 +468,34 @@ static av_cold void uninit(AVFilterContext *ctx)
{
ReadEIA608Context
*
s
=
ctx
->
priv
;
av_freep
(
&
s
->
code
);
av_freep
(
&
s
->
line
);
for
(
int
i
=
0
;
i
<
s
->
nb_allocated
;
i
++
)
{
ScanItem
*
scan
=
&
s
->
scan
[
i
];
av_freep
(
&
scan
->
code
);
av_freep
(
&
scan
->
line
);
}
s
->
nb_allocated
=
0
;
av_freep
(
&
s
->
scan
);
}
static
int
process_command
(
AVFilterContext
*
ctx
,
const
char
*
cmd
,
const
char
*
args
,
char
*
res
,
int
res_len
,
int
flags
)
{
ReadEIA608Context
*
s
=
ctx
->
priv
;
int
ret
,
start
=
s
->
start
,
end
=
s
->
end
;
ret
=
ff_filter_process_command
(
ctx
,
cmd
,
args
,
res
,
res_len
,
flags
);
if
(
ret
<
0
)
return
ret
;
ret
=
config_filter
(
ctx
,
s
->
start
,
s
->
end
);
if
(
ret
<
0
)
{
s
->
start
=
start
;
s
->
end
=
end
;
}
return
0
;
}
static
const
AVFilterPad
readeia608_inputs
[]
=
{
...
...
@@ -439,6 +525,6 @@ AVFilter ff_vf_readeia608 = {
.
inputs
=
readeia608_inputs
,
.
outputs
=
readeia608_outputs
,
.
uninit
=
uninit
,
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,
.
process_command
=
ff_filter_
process_command
,
.
flags
=
AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
|
AVFILTER_FLAG_SLICE_THREADS
,
.
process_command
=
process_command
,
};
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