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
1730a67a
Commit
1730a67a
authored
Aug 02, 2016
by
Ronald S. Bultje
Committed by
Anton Khirnov
Aug 11, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
vp9: add frame threading
Signed-off-by:
Anton Khirnov
<
anton@khirnov.net
>
parent
5b995452
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
318 additions
and
81 deletions
+318
-81
vp9.c
libavcodec/vp9.c
+225
-48
vp9.h
libavcodec/vp9.h
+11
-0
vp9block.c
libavcodec/vp9block.c
+78
-33
vp9mvs.c
libavcodec/vp9mvs.c
+4
-0
No files found.
libavcodec/vp9.c
View file @
1730a67a
...
...
@@ -105,14 +105,20 @@ static void vp9_decode_flush(AVCodecContext *avctx)
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
s
->
refs
);
i
++
)
ff_thread_release_buffer
(
avctx
,
&
s
->
refs
[
i
]);
s
->
use_last_frame_mvs
=
0
;
s
->
alloc_width
=
0
;
s
->
alloc_height
=
0
;
}
static
int
update_size
(
AVCodecContext
*
avctx
,
int
w
,
int
h
)
{
VP9Context
*
s
=
avctx
->
priv_data
;
uint8_t
*
p
;
int
nb_blocks
,
nb_superblocks
;
if
(
s
->
above_partition_ctx
&&
w
==
avctx
->
width
&&
h
==
avctx
->
height
)
if
(
s
->
above_partition_ctx
&&
w
==
s
->
alloc_width
&&
h
==
s
->
alloc_
height
)
return
0
;
vp9_decode_flush
(
avctx
);
...
...
@@ -154,16 +160,26 @@ static int update_size(AVCodecContext *avctx, int w, int h)
av_freep
(
&
s
->
b_base
);
av_freep
(
&
s
->
block_base
);
s
->
b_base
=
av_malloc
(
sizeof
(
*
s
->
b_base
));
s
->
block_base
=
av_mallocz
((
64
*
64
+
128
)
*
3
);
if
(
avctx
->
active_thread_type
&
FF_THREAD_FRAME
)
{
nb_blocks
=
s
->
cols
*
s
->
rows
;
nb_superblocks
=
s
->
sb_cols
*
s
->
sb_rows
;
}
else
{
nb_blocks
=
nb_superblocks
=
1
;
}
s
->
b_base
=
av_malloc_array
(
nb_blocks
,
sizeof
(
*
s
->
b_base
));
s
->
block_base
=
av_mallocz_array
(
nb_superblocks
,
(
64
*
64
+
128
)
*
3
);
if
(
!
s
->
b_base
||
!
s
->
block_base
)
return
AVERROR
(
ENOMEM
);
s
->
uvblock_base
[
0
]
=
s
->
block_base
+
nb_superblocks
*
64
*
64
;
s
->
uvblock_base
[
1
]
=
s
->
uvblock_base
[
0
]
+
nb_superblocks
*
32
*
32
;
s
->
eob_base
=
(
uint8_t
*
)(
s
->
uvblock_base
[
1
]
+
nb_superblocks
*
32
*
32
);
s
->
uveob_base
[
0
]
=
s
->
eob_base
+
nb_superblocks
*
256
;
s
->
uveob_base
[
1
]
=
s
->
uveob_base
[
0
]
+
nb_superblocks
*
64
;
s
->
uvblock_base
[
0
]
=
s
->
block_base
+
64
*
64
;
s
->
uvblock_base
[
1
]
=
s
->
uvblock_base
[
0
]
+
32
*
32
;
s
->
eob_base
=
(
uint8_t
*
)
(
s
->
uvblock_base
[
1
]
+
32
*
32
);
s
->
uveob_base
[
0
]
=
s
->
eob_base
+
256
;
s
->
uveob_base
[
1
]
=
s
->
uveob_base
[
0
]
+
64
;
s
->
alloc_width
=
w
;
s
->
alloc_height
=
h
;
return
0
;
}
...
...
@@ -278,7 +294,6 @@ static int decode_frame_header(AVCodecContext *avctx,
last_invisible
=
s
->
invisible
;
s
->
invisible
=
!
get_bits1
(
&
s
->
gb
);
s
->
errorres
=
get_bits1
(
&
s
->
gb
);
// FIXME disable this upon resolution change
s
->
use_last_frame_mvs
=
!
s
->
errorres
&&
!
last_invisible
;
if
(
s
->
keyframe
)
{
...
...
@@ -851,6 +866,61 @@ static int decode_subblock(AVCodecContext *avctx, int row, int col,
return
ret
;
}
static
int
decode_superblock_mem
(
AVCodecContext
*
avctx
,
int
row
,
int
col
,
struct
VP9Filter
*
lflvl
,
ptrdiff_t
yoff
,
ptrdiff_t
uvoff
,
enum
BlockLevel
bl
)
{
VP9Context
*
s
=
avctx
->
priv_data
;
VP9Block
*
b
=
s
->
b
;
ptrdiff_t
hbs
=
4
>>
bl
;
AVFrame
*
f
=
s
->
frames
[
CUR_FRAME
].
tf
.
f
;
ptrdiff_t
y_stride
=
f
->
linesize
[
0
],
uv_stride
=
f
->
linesize
[
1
];
int
res
;
if
(
bl
==
BL_8X8
)
{
av_assert2
(
b
->
bl
==
BL_8X8
);
res
=
ff_vp9_decode_block
(
avctx
,
row
,
col
,
lflvl
,
yoff
,
uvoff
,
b
->
bl
,
b
->
bp
);
}
else
if
(
s
->
b
->
bl
==
bl
)
{
if
((
res
=
ff_vp9_decode_block
(
avctx
,
row
,
col
,
lflvl
,
yoff
,
uvoff
,
b
->
bl
,
b
->
bp
))
<
0
)
return
res
;
if
(
b
->
bp
==
PARTITION_H
&&
row
+
hbs
<
s
->
rows
)
{
yoff
+=
hbs
*
8
*
y_stride
;
uvoff
+=
hbs
*
4
*
uv_stride
;
res
=
ff_vp9_decode_block
(
avctx
,
row
+
hbs
,
col
,
lflvl
,
yoff
,
uvoff
,
b
->
bl
,
b
->
bp
);
}
else
if
(
b
->
bp
==
PARTITION_V
&&
col
+
hbs
<
s
->
cols
)
{
yoff
+=
hbs
*
8
;
uvoff
+=
hbs
*
4
;
res
=
ff_vp9_decode_block
(
avctx
,
row
,
col
+
hbs
,
lflvl
,
yoff
,
uvoff
,
b
->
bl
,
b
->
bp
);
}
}
else
{
if
((
res
=
decode_superblock_mem
(
avctx
,
row
,
col
,
lflvl
,
yoff
,
uvoff
,
bl
+
1
))
<
0
)
return
res
;
if
(
col
+
hbs
<
s
->
cols
)
{
// FIXME why not <=?
if
(
row
+
hbs
<
s
->
rows
)
{
if
((
res
=
decode_superblock_mem
(
avctx
,
row
,
col
+
hbs
,
lflvl
,
yoff
+
8
*
hbs
,
uvoff
+
4
*
hbs
,
bl
+
1
))
<
0
)
return
res
;
yoff
+=
hbs
*
8
*
y_stride
;
uvoff
+=
hbs
*
4
*
uv_stride
;
if
((
res
=
decode_superblock_mem
(
avctx
,
row
+
hbs
,
col
,
lflvl
,
yoff
,
uvoff
,
bl
+
1
))
<
0
)
return
res
;
res
=
decode_superblock_mem
(
avctx
,
row
+
hbs
,
col
+
hbs
,
lflvl
,
yoff
+
8
*
hbs
,
uvoff
+
4
*
hbs
,
bl
+
1
);
}
else
{
yoff
+=
hbs
*
8
;
uvoff
+=
hbs
*
4
;
res
=
decode_superblock_mem
(
avctx
,
row
,
col
+
hbs
,
lflvl
,
yoff
,
uvoff
,
bl
+
1
);
}
}
else
if
(
row
+
hbs
<
s
->
rows
)
{
yoff
+=
hbs
*
8
*
y_stride
;
uvoff
+=
hbs
*
4
*
uv_stride
;
res
=
decode_superblock_mem
(
avctx
,
row
+
hbs
,
col
,
lflvl
,
yoff
,
uvoff
,
bl
+
1
);
}
}
return
res
;
}
static
void
loopfilter_subblock
(
AVCodecContext
*
avctx
,
VP9Filter
*
lflvl
,
int
row
,
int
col
,
ptrdiff_t
yoff
,
ptrdiff_t
uvoff
)
...
...
@@ -1102,13 +1172,29 @@ static void set_tile_offset(int *start, int *end, int idx, int log2_n, int n)
*
end
=
FFMIN
(
sb_end
,
n
)
<<
3
;
}
static
int
update_refs
(
AVCodecContext
*
avctx
)
{
VP9Context
*
s
=
avctx
->
priv_data
;
int
i
,
ret
;
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
s
->
refs
);
i
++
)
if
(
s
->
refreshrefmask
&
(
1
<<
i
))
{
ff_thread_release_buffer
(
avctx
,
&
s
->
refs
[
i
]);
ret
=
ff_thread_ref_frame
(
&
s
->
refs
[
i
],
&
s
->
frames
[
CUR_FRAME
].
tf
);
if
(
ret
<
0
)
return
ret
;
}
return
0
;
}
static
int
vp9_decode_frame
(
AVCodecContext
*
avctx
,
AVFrame
*
frame
,
int
*
got_frame
,
const
uint8_t
*
data
,
int
size
)
int
*
got_frame
,
const
uint8_t
*
data
,
int
size
,
int
can_finish_setup
)
{
VP9Context
*
s
=
avctx
->
priv_data
;
AVFrame
*
f
;
int
ret
,
tile_row
,
tile_col
,
i
,
ref
=
-
1
,
row
,
col
;
ptrdiff_t
yoff
=
0
,
uvoff
=
0
;
ret
=
decode_frame_header
(
avctx
,
data
,
size
,
&
ref
);
if
(
ret
<
0
)
{
...
...
@@ -1157,6 +1243,29 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
case
4
:
avctx
->
colorspace
=
AVCOL_SPC_SMPTE240M
;
break
;
}
s
->
pass
=
s
->
uses_2pass
=
avctx
->
active_thread_type
&
FF_THREAD_FRAME
&&
s
->
refreshctx
&&
!
s
->
parallelmode
;
if
(
s
->
refreshctx
&&
s
->
parallelmode
)
{
int
j
,
k
,
l
,
m
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
for
(
j
=
0
;
j
<
2
;
j
++
)
for
(
k
=
0
;
k
<
2
;
k
++
)
for
(
l
=
0
;
l
<
6
;
l
++
)
for
(
m
=
0
;
m
<
6
;
m
++
)
memcpy
(
s
->
prob_ctx
[
s
->
framectxid
].
coef
[
i
][
j
][
k
][
l
][
m
],
s
->
prob
.
coef
[
i
][
j
][
k
][
l
][
m
],
3
);
if
(
s
->
txfmmode
==
i
)
break
;
}
s
->
prob_ctx
[
s
->
framectxid
].
p
=
s
->
prob
.
p
;
}
if
((
s
->
parallelmode
||
!
s
->
refreshctx
)
&&
can_finish_setup
&&
avctx
->
active_thread_type
&
FF_THREAD_FRAME
)
{
ff_thread_finish_setup
(
avctx
);
s
->
setup_finished
=
1
;
}
// main tile decode loop
memset
(
s
->
above_partition_ctx
,
0
,
s
->
cols
);
memset
(
s
->
above_skip_ctx
,
0
,
s
->
cols
);
...
...
@@ -1169,6 +1278,8 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
memset
(
s
->
above_uv_nnz_ctx
[
1
],
0
,
s
->
sb_cols
*
8
);
memset
(
s
->
above_segpred_ctx
,
0
,
s
->
cols
);
do
{
ptrdiff_t
yoff
=
0
,
uvoff
=
0
;
s
->
b
=
s
->
b_base
;
s
->
block
=
s
->
block_base
;
s
->
uvblock
[
0
]
=
s
->
uvblock_base
[
0
];
...
...
@@ -1180,6 +1291,8 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
for
(
tile_row
=
0
;
tile_row
<
s
->
tiling
.
tile_rows
;
tile_row
++
)
{
set_tile_offset
(
&
s
->
tiling
.
tile_row_start
,
&
s
->
tiling
.
tile_row_end
,
tile_row
,
s
->
tiling
.
log2_tile_rows
,
s
->
sb_rows
);
if
(
s
->
pass
!=
2
)
{
for
(
tile_col
=
0
;
tile_col
<
s
->
tiling
.
tile_cols
;
tile_col
++
)
{
int64_t
tile_size
;
...
...
@@ -1191,14 +1304,19 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
data
+=
4
;
size
-=
4
;
}
if
(
tile_size
>
size
)
return
AVERROR_INVALIDDATA
;
if
(
tile_size
>
size
)
{
ret
=
AVERROR_INVALIDDATA
;
goto
fail
;
}
ff_vp56_init_range_decoder
(
&
s
->
c_b
[
tile_col
],
data
,
tile_size
);
if
(
vp56_rac_get_prob_branchy
(
&
s
->
c_b
[
tile_col
],
128
))
// marker bit
return
AVERROR_INVALIDDATA
;
if
(
vp56_rac_get_prob_branchy
(
&
s
->
c_b
[
tile_col
],
128
))
{
// marker bit
ret
=
AVERROR_INVALIDDATA
;
goto
fail
;
}
data
+=
tile_size
;
size
-=
tile_size
;
}
}
for
(
row
=
s
->
tiling
.
tile_row_start
;
row
<
s
->
tiling
.
tile_row_end
;
...
...
@@ -1228,15 +1346,26 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
col
+=
8
,
yoff2
+=
64
,
uvoff2
+=
32
,
lflvl
++
)
{
// FIXME integrate with lf code (i.e. zero after each
// use, similar to invtxfm coefficients, or similar)
if
(
s
->
pass
!=
1
)
memset
(
lflvl
->
mask
,
0
,
sizeof
(
lflvl
->
mask
));
if
((
ret
=
decode_subblock
(
avctx
,
row
,
col
,
lflvl
,
yoff2
,
uvoff2
,
BL_64X64
))
<
0
)
return
ret
;
if
(
s
->
pass
==
2
)
{
ret
=
decode_superblock_mem
(
avctx
,
row
,
col
,
lflvl
,
yoff2
,
uvoff2
,
BL_64X64
);
}
else
{
ret
=
decode_subblock
(
avctx
,
row
,
col
,
lflvl
,
yoff2
,
uvoff2
,
BL_64X64
);
}
if
(
ret
<
0
)
goto
fail
;
}
if
(
s
->
pass
!=
2
)
memcpy
(
&
s
->
c_b
[
tile_col
],
&
s
->
c
,
sizeof
(
s
->
c
));
}
if
(
s
->
pass
==
1
)
continue
;
// backup pre-loopfilter reconstruction data for intra
// prediction of next row of sb64s
if
(
row
+
8
<
s
->
rows
)
{
...
...
@@ -1263,35 +1392,30 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
col
+=
8
,
yoff2
+=
64
,
uvoff2
+=
32
,
lflvl
++
)
loopfilter_subblock
(
avctx
,
lflvl
,
row
,
col
,
yoff2
,
uvoff2
);
}
// FIXME maybe we can make this more finegrained by running the
// loopfilter per-block instead of after each sbrow
// In fact that would also make intra pred left preparation easier?
ff_thread_report_progress
(
&
s
->
frames
[
CUR_FRAME
].
tf
,
row
>>
3
,
0
);
}
}
// bw adaptivity (or in case of parallel decoding mode, fw adaptivity
// probability maintenance between frames)
if
(
s
->
refreshctx
)
{
if
(
s
->
parallelmode
)
{
int
j
,
k
,
l
,
m
;
for
(
i
=
0
;
i
<
4
;
i
++
)
{
for
(
j
=
0
;
j
<
2
;
j
++
)
for
(
k
=
0
;
k
<
2
;
k
++
)
for
(
l
=
0
;
l
<
6
;
l
++
)
for
(
m
=
0
;
m
<
6
;
m
++
)
memcpy
(
s
->
prob_ctx
[
s
->
framectxid
].
coef
[
i
][
j
][
k
][
l
][
m
],
s
->
prob
.
coef
[
i
][
j
][
k
][
l
][
m
],
3
);
if
(
s
->
txfmmode
==
i
)
break
;
}
s
->
prob_ctx
[
s
->
framectxid
].
p
=
s
->
prob
.
p
;
}
else
{
if
(
s
->
pass
<
2
&&
s
->
refreshctx
&&
!
s
->
parallelmode
)
{
ff_vp9_adapt_probs
(
s
);
if
(
can_finish_setup
&&
avctx
->
active_thread_type
&
FF_THREAD_FRAME
)
{
ff_thread_finish_setup
(
avctx
);
s
->
setup_finished
=
1
;
}
}
}
while
(
s
->
pass
++
==
1
);
fail:
ff_thread_report_progress
(
&
s
->
frames
[
CUR_FRAME
].
tf
,
INT_MAX
,
0
);
if
(
ret
<
0
)
return
ret
;
// ref frame setup
for
(
i
=
0
;
i
<
8
;
i
++
)
if
(
s
->
refreshrefmask
&
(
1
<<
i
))
{
ff_thread_release_buffer
(
avctx
,
&
s
->
refs
[
i
]);
ret
=
ff_thread_ref_frame
(
&
s
->
refs
[
i
],
&
s
->
frames
[
CUR_FRAME
].
tf
);
if
(
!
s
->
setup_finished
)
{
ret
=
update_refs
(
avctx
);
if
(
ret
<
0
)
return
ret
;
}
...
...
@@ -1310,10 +1434,13 @@ static int vp9_decode_frame(AVCodecContext *avctx, AVFrame *frame,
static
int
vp9_decode_packet
(
AVCodecContext
*
avctx
,
void
*
frame
,
int
*
got_frame
,
AVPacket
*
avpkt
)
{
VP9Context
*
s
=
avctx
->
priv_data
;
const
uint8_t
*
data
=
avpkt
->
data
;
int
size
=
avpkt
->
size
;
int
marker
,
ret
;
s
->
setup_finished
=
0
;
/* Read superframe index - this is a collection of individual frames
* that together lead to one visible frame */
marker
=
data
[
size
-
1
];
...
...
@@ -1339,7 +1466,8 @@ static int vp9_decode_packet(AVCodecContext *avctx, void *frame,
return
AVERROR_INVALIDDATA
;
}
ret
=
vp9_decode_frame
(
avctx
,
frame
,
got_frame
,
data
,
sz
);
ret
=
vp9_decode_frame
(
avctx
,
frame
,
got_frame
,
data
,
sz
,
!
n_frames
);
if
(
ret
<
0
)
return
ret
;
data
+=
sz
;
...
...
@@ -1351,7 +1479,7 @@ static int vp9_decode_packet(AVCodecContext *avctx, void *frame,
/* If we get here, there was no valid superframe index, i.e. this is just
* one whole single frame. Decode it as such from the complete input buf. */
if
((
ret
=
vp9_decode_frame
(
avctx
,
frame
,
got_frame
,
data
,
size
))
<
0
)
if
((
ret
=
vp9_decode_frame
(
avctx
,
frame
,
got_frame
,
data
,
size
,
1
))
<
0
)
return
ret
;
return
size
;
}
...
...
@@ -1384,6 +1512,10 @@ static av_cold int vp9_decode_init(AVCodecContext *avctx)
VP9Context
*
s
=
avctx
->
priv_data
;
int
i
;
memset
(
s
,
0
,
sizeof
(
*
s
));
avctx
->
internal
->
allocate_progress
=
1
;
avctx
->
pix_fmt
=
AV_PIX_FMT_YUV420P
;
ff_vp9dsp_init
(
&
s
->
dsp
);
...
...
@@ -1408,6 +1540,49 @@ fail:
return
AVERROR
(
ENOMEM
);
}
static
int
vp9_decode_update_thread_context
(
AVCodecContext
*
dst
,
const
AVCodecContext
*
src
)
{
VP9Context
*
s
=
dst
->
priv_data
,
*
ssrc
=
src
->
priv_data
;
int
i
,
ret
;
ret
=
update_size
(
dst
,
ssrc
->
alloc_width
,
ssrc
->
alloc_height
);
if
(
ret
<
0
)
return
ret
;
for
(
i
=
0
;
i
<
2
;
i
++
)
{
if
(
s
->
frames
[
i
].
tf
.
f
->
data
[
0
])
vp9_frame_unref
(
dst
,
&
s
->
frames
[
i
]);
if
(
ssrc
->
frames
[
i
].
tf
.
f
->
data
[
0
])
{
if
((
ret
=
vp9_frame_ref
(
&
s
->
frames
[
i
],
&
ssrc
->
frames
[
i
]))
<
0
)
return
ret
;
}
}
for
(
i
=
0
;
i
<
FF_ARRAY_ELEMS
(
s
->
refs
);
i
++
)
{
ff_thread_release_buffer
(
dst
,
&
s
->
refs
[
i
]);
if
(
ssrc
->
refs
[
i
].
f
->
buf
[
0
])
{
ret
=
ff_thread_ref_frame
(
&
s
->
refs
[
i
],
&
ssrc
->
refs
[
i
]);
if
(
ret
<
0
)
return
ret
;
}
}
s
->
refreshrefmask
=
ssrc
->
refreshrefmask
;
ret
=
update_refs
(
dst
);
if
(
ret
<
0
)
return
ret
;
s
->
invisible
=
ssrc
->
invisible
;
s
->
keyframe
=
ssrc
->
keyframe
;
s
->
last_uses_2pass
=
ssrc
->
uses_2pass
;
memcpy
(
&
s
->
prob_ctx
,
&
ssrc
->
prob_ctx
,
sizeof
(
s
->
prob_ctx
));
memcpy
(
&
s
->
lf_delta
,
&
ssrc
->
lf_delta
,
sizeof
(
s
->
lf_delta
));
memcpy
(
&
s
->
segmentation
.
feat
,
&
ssrc
->
segmentation
.
feat
,
sizeof
(
s
->
segmentation
.
feat
));
return
0
;
}
AVCodec
ff_vp9_decoder
=
{
.
name
=
"vp9"
,
.
long_name
=
NULL_IF_CONFIG_SMALL
(
"Google VP9"
),
...
...
@@ -1418,5 +1593,7 @@ AVCodec ff_vp9_decoder = {
.
decode
=
vp9_decode_packet
,
.
flush
=
vp9_decode_flush
,
.
close
=
vp9_decode_free
,
.
capabilities
=
AV_CODEC_CAP_DR1
,
.
capabilities
=
AV_CODEC_CAP_DR1
|
AV_CODEC_CAP_FRAME_THREADS
,
.
init_thread_copy
=
vp9_decode_init
,
.
update_thread_context
=
vp9_decode_update_thread_context
,
};
libavcodec/vp9.h
View file @
1730a67a
...
...
@@ -271,6 +271,9 @@ typedef struct VP9Block {
int
row
,
row7
,
col
,
col7
;
uint8_t
*
dst
[
3
];
ptrdiff_t
y_stride
,
uv_stride
;
enum
BlockLevel
bl
;
enum
BlockPartition
bp
;
}
VP9Block
;
typedef
struct
VP9Context
{
...
...
@@ -283,6 +286,14 @@ typedef struct VP9Context {
VP9Block
*
b
;
VP9Block
*
b_base
;
int
alloc_width
;
int
alloc_height
;
int
pass
;
int
uses_2pass
;
int
last_uses_2pass
;
int
setup_finished
;
// bitstream header
uint8_t
profile
;
uint8_t
keyframe
,
last_keyframe
;
...
...
libavcodec/vp9block.c
View file @
1730a67a
...
...
@@ -74,6 +74,9 @@ static void decode_mode(VP9Context *s, VP9Block *const b)
int
pred
=
MAX_SEGMENT
-
1
;
int
x
;
if
(
!
s
->
last_uses_2pass
)
ff_thread_await_progress
(
&
s
->
frames
[
LAST_FRAME
].
tf
,
row
>>
3
,
0
);
for
(
y
=
0
;
y
<
h4
;
y
++
)
for
(
x
=
0
;
x
<
w4
;
x
++
)
pred
=
FFMIN
(
pred
,
...
...
@@ -1149,17 +1152,25 @@ static av_always_inline void mc_luma_dir(VP9Context *s, vp9_mc_func(*mc)[2],
uint8_t
*
dst
,
ptrdiff_t
dst_stride
,
const
uint8_t
*
ref
,
ptrdiff_t
ref_stride
,
ThreadFrame
*
ref_frame
,
ptrdiff_t
y
,
ptrdiff_t
x
,
const
VP56mv
*
mv
,
int
bw
,
int
bh
,
int
w
,
int
h
)
{
int
mx
=
mv
->
x
,
my
=
mv
->
y
;
int
th
;
y
+=
my
>>
3
;
x
+=
mx
>>
3
;
ref
+=
y
*
ref_stride
+
x
;
mx
&=
7
;
my
&=
7
;
// we use +7 because the last 7 pixels of each sbrow can be changed in
// the longest loopfilter of the next sbrow
th
=
(
y
+
bh
+
4
*
!!
my
+
7
)
>>
6
;
ff_thread_await_progress
(
ref_frame
,
FFMAX
(
th
,
0
),
0
);
// FIXME bilinear filter only needs 0/1 pixels, not 3/4
if
(
x
<
!!
mx
*
3
||
y
<
!!
my
*
3
||
x
+
!!
mx
*
4
>
w
-
bw
||
y
+
!!
my
*
4
>
h
-
bh
)
{
...
...
@@ -1182,11 +1193,13 @@ static av_always_inline void mc_chroma_dir(VP9Context *s, vp9_mc_func(*mc)[2],
ptrdiff_t
src_stride_u
,
const
uint8_t
*
ref_v
,
ptrdiff_t
src_stride_v
,
ThreadFrame
*
ref_frame
,
ptrdiff_t
y
,
ptrdiff_t
x
,
const
VP56mv
*
mv
,
int
bw
,
int
bh
,
int
w
,
int
h
)
{
int
mx
=
mv
->
x
,
my
=
mv
->
y
;
int
th
;
y
+=
my
>>
4
;
x
+=
mx
>>
4
;
...
...
@@ -1194,6 +1207,12 @@ static av_always_inline void mc_chroma_dir(VP9Context *s, vp9_mc_func(*mc)[2],
ref_v
+=
y
*
src_stride_v
+
x
;
mx
&=
15
;
my
&=
15
;
// we use +7 because the last 7 pixels of each sbrow can be changed in
// the longest loopfilter of the next sbrow
th
=
(
y
+
bh
+
4
*
!!
my
+
7
)
>>
5
;
ff_thread_await_progress
(
ref_frame
,
FFMAX
(
th
,
0
),
0
);
// FIXME bilinear filter only needs 0/1 pixels, not 3/4
if
(
x
<
!!
mx
*
3
||
y
<
!!
my
*
3
||
x
+
!!
mx
*
4
>
w
-
bw
||
y
+
!!
my
*
4
>
h
-
bh
)
{
...
...
@@ -1245,36 +1264,36 @@ static int inter_recon(AVCodecContext *avctx)
if
(
b
->
bs
>
BS_8x8
)
{
if
(
b
->
bs
==
BS_8x4
)
{
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
3
][
b
->
filter
][
0
],
b
->
dst
[
0
],
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
row
<<
3
,
col
<<
3
,
&
b
->
mv
[
0
][
0
],
8
,
4
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
3
][
b
->
filter
][
0
],
b
->
dst
[
0
]
+
4
*
ls_y
,
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
(
row
<<
3
)
+
4
,
col
<<
3
,
&
b
->
mv
[
2
][
0
],
8
,
4
,
w
,
h
);
if
(
b
->
comp
)
{
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
3
][
b
->
filter
][
1
],
b
->
dst
[
0
],
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
row
<<
3
,
col
<<
3
,
&
b
->
mv
[
0
][
1
],
8
,
4
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
3
][
b
->
filter
][
1
],
b
->
dst
[
0
]
+
4
*
ls_y
,
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
(
row
<<
3
)
+
4
,
col
<<
3
,
&
b
->
mv
[
2
][
1
],
8
,
4
,
w
,
h
);
}
}
else
if
(
b
->
bs
==
BS_4x8
)
{
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
0
],
b
->
dst
[
0
],
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
row
<<
3
,
col
<<
3
,
&
b
->
mv
[
0
][
0
],
4
,
8
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
0
],
b
->
dst
[
0
]
+
4
,
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
row
<<
3
,
(
col
<<
3
)
+
4
,
&
b
->
mv
[
1
][
0
],
4
,
8
,
w
,
h
);
if
(
b
->
comp
)
{
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
1
],
b
->
dst
[
0
],
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
row
<<
3
,
col
<<
3
,
&
b
->
mv
[
0
][
1
],
4
,
8
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
1
],
b
->
dst
[
0
]
+
4
,
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
row
<<
3
,
(
col
<<
3
)
+
4
,
&
b
->
mv
[
1
][
1
],
4
,
8
,
w
,
h
);
}
}
else
{
...
...
@@ -1283,34 +1302,34 @@ static int inter_recon(AVCodecContext *avctx)
// FIXME if two horizontally adjacent blocks have the same MV,
// do a w8 instead of a w4 call
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
0
],
b
->
dst
[
0
],
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
row
<<
3
,
col
<<
3
,
&
b
->
mv
[
0
][
0
],
4
,
4
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
0
],
b
->
dst
[
0
]
+
4
,
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
row
<<
3
,
(
col
<<
3
)
+
4
,
&
b
->
mv
[
1
][
0
],
4
,
4
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
0
],
b
->
dst
[
0
]
+
4
*
ls_y
,
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
(
row
<<
3
)
+
4
,
col
<<
3
,
&
b
->
mv
[
2
][
0
],
4
,
4
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
0
],
b
->
dst
[
0
]
+
4
*
ls_y
+
4
,
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
(
row
<<
3
)
+
4
,
(
col
<<
3
)
+
4
,
&
b
->
mv
[
3
][
0
],
4
,
4
,
w
,
h
);
if
(
b
->
comp
)
{
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
1
],
b
->
dst
[
0
],
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
row
<<
3
,
col
<<
3
,
&
b
->
mv
[
0
][
1
],
4
,
4
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
1
],
b
->
dst
[
0
]
+
4
,
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
row
<<
3
,
(
col
<<
3
)
+
4
,
&
b
->
mv
[
1
][
1
],
4
,
4
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
1
],
b
->
dst
[
0
]
+
4
*
ls_y
,
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
(
row
<<
3
)
+
4
,
col
<<
3
,
&
b
->
mv
[
2
][
1
],
4
,
4
,
w
,
h
);
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
4
][
b
->
filter
][
1
],
b
->
dst
[
0
]
+
4
*
ls_y
+
4
,
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
(
row
<<
3
)
+
4
,
(
col
<<
3
)
+
4
,
&
b
->
mv
[
3
][
1
],
4
,
4
,
w
,
h
);
}
}
...
...
@@ -1320,12 +1339,12 @@ static int inter_recon(AVCodecContext *avctx)
int
bh
=
bwh_tab
[
0
][
b
->
bs
][
1
]
*
4
;
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
bwl
][
b
->
filter
][
0
],
b
->
dst
[
0
],
ls_y
,
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
ref1
->
data
[
0
],
ref1
->
linesize
[
0
],
tref1
,
row
<<
3
,
col
<<
3
,
&
b
->
mv
[
0
][
0
],
bw
,
bh
,
w
,
h
);
if
(
b
->
comp
)
mc_luma_dir
(
s
,
s
->
dsp
.
mc
[
bwl
][
b
->
filter
][
1
],
b
->
dst
[
0
],
ls_y
,
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
ref2
->
data
[
0
],
ref2
->
linesize
[
0
],
tref2
,
row
<<
3
,
col
<<
3
,
&
b
->
mv
[
0
][
1
],
bw
,
bh
,
w
,
h
);
}
...
...
@@ -1349,7 +1368,7 @@ static int inter_recon(AVCodecContext *avctx)
mc_chroma_dir
(
s
,
s
->
dsp
.
mc
[
bwl
][
b
->
filter
][
0
],
b
->
dst
[
1
],
b
->
dst
[
2
],
ls_uv
,
ref1
->
data
[
1
],
ref1
->
linesize
[
1
],
ref1
->
data
[
2
],
ref1
->
linesize
[
2
],
ref1
->
data
[
2
],
ref1
->
linesize
[
2
],
tref1
,
row
<<
2
,
col
<<
2
,
&
mvuv
,
bw
,
bh
,
w
,
h
);
if
(
b
->
comp
)
{
...
...
@@ -1364,7 +1383,7 @@ static int inter_recon(AVCodecContext *avctx)
mc_chroma_dir
(
s
,
s
->
dsp
.
mc
[
bwl
][
b
->
filter
][
1
],
b
->
dst
[
1
],
b
->
dst
[
2
],
ls_uv
,
ref2
->
data
[
1
],
ref2
->
linesize
[
1
],
ref2
->
data
[
2
],
ref2
->
linesize
[
2
],
ref2
->
data
[
2
],
ref2
->
linesize
[
2
],
tref2
,
row
<<
2
,
col
<<
2
,
&
mvuv
,
bw
,
bh
,
w
,
h
);
}
}
...
...
@@ -1571,7 +1590,10 @@ int ff_vp9_decode_block(AVCodecContext *avctx, int row, int col,
s
->
max_mv
.
x
=
128
+
(
s
->
cols
-
col
-
w4
)
*
64
;
s
->
max_mv
.
y
=
128
+
(
s
->
rows
-
row
-
h4
)
*
64
;
if
(
s
->
pass
<
2
)
{
b
->
bs
=
bs
;
b
->
bl
=
bl
;
b
->
bp
=
bp
;
decode_mode
(
s
,
b
);
b
->
uvtx
=
b
->
tx
-
(
w4
*
2
==
(
1
<<
b
->
tx
)
||
h4
*
2
==
(
1
<<
b
->
tx
));
...
...
@@ -1589,6 +1611,19 @@ int ff_vp9_decode_block(AVCodecContext *avctx, int row, int col,
}
}
if
(
s
->
pass
==
1
)
{
s
->
b
++
;
s
->
block
+=
w4
*
h4
*
64
;
s
->
uvblock
[
0
]
+=
w4
*
h4
*
16
;
s
->
uvblock
[
1
]
+=
w4
*
h4
*
16
;
s
->
eob
+=
w4
*
h4
*
4
;
s
->
uveob
[
0
]
+=
w4
*
h4
;
s
->
uveob
[
1
]
+=
w4
*
h4
;
return
0
;
}
}
/* Emulated overhangs if the stride of the target buffer can't hold.
* This allows to support emu-edge and so on even if we have large
* block overhangs. */
...
...
@@ -1690,5 +1725,15 @@ int ff_vp9_decode_block(AVCodecContext *avctx, int row, int col,
}
}
if
(
s
->
pass
==
2
)
{
s
->
b
++
;
s
->
block
+=
w4
*
h4
*
64
;
s
->
uvblock
[
0
]
+=
w4
*
h4
*
16
;
s
->
uvblock
[
1
]
+=
w4
*
h4
*
16
;
s
->
eob
+=
w4
*
h4
*
4
;
s
->
uveob
[
0
]
+=
w4
*
h4
;
s
->
uveob
[
1
]
+=
w4
*
h4
;
}
return
0
;
}
libavcodec/vp9mvs.c
View file @
1730a67a
...
...
@@ -164,6 +164,9 @@ static void find_ref_mvs(VP9Context *s,
if
(
s
->
use_last_frame_mvs
)
{
VP9MVRefPair
*
mv
=
&
s
->
frames
[
LAST_FRAME
].
mv
[
row
*
s
->
sb_cols
*
8
+
col
];
if
(
!
s
->
last_uses_2pass
)
ff_thread_await_progress
(
&
s
->
frames
[
LAST_FRAME
].
tf
,
row
>>
3
,
0
);
if
(
mv
->
ref
[
0
]
==
ref
)
RETURN_MV
(
mv
->
mv
[
0
]);
else
if
(
mv
->
ref
[
1
]
==
ref
)
...
...
@@ -205,6 +208,7 @@ static void find_ref_mvs(VP9Context *s,
if
(
s
->
use_last_frame_mvs
)
{
VP9MVRefPair
*
mv
=
&
s
->
frames
[
LAST_FRAME
].
mv
[
row
*
s
->
sb_cols
*
8
+
col
];
// no need to await_progress, because we already did that above
if
(
mv
->
ref
[
0
]
!=
ref
&&
mv
->
ref
[
0
]
>=
0
)
RETURN_SCALE_MV
(
mv
->
mv
[
0
],
s
->
signbias
[
mv
->
ref
[
0
]]
!=
s
->
signbias
[
ref
]);
...
...
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