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
08aec6f6
Commit
08aec6f6
authored
Dec 03, 2014
by
Benoit Fouet
Committed by
Michael Niedermayer
Dec 03, 2014
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
libavcodec/pngdec: support 'previous' dispose operation for APNG.
Signed-off-by:
Michael Niedermayer
<
michaelni@gmx.at
>
parent
49d9cbe5
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
50 additions
and
22 deletions
+50
-22
pngdec.c
libavcodec/pngdec.c
+50
-22
No files found.
libavcodec/pngdec.c
View file @
08aec6f6
...
...
@@ -38,6 +38,7 @@ typedef struct PNGDecContext {
AVCodecContext
*
avctx
;
GetByteContext
gb
;
ThreadFrame
previous_picture
;
ThreadFrame
last_picture
;
ThreadFrame
picture
;
...
...
@@ -55,6 +56,7 @@ typedef struct PNGDecContext {
int
bits_per_pixel
;
int
bpp
;
int
frame_id
;
uint8_t
*
image_buf
;
int
image_linesize
;
uint32_t
palette
[
256
];
...
...
@@ -827,13 +829,14 @@ static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s,
return
AVERROR_INVALIDDATA
;
/* always (re)start with a clean frame */
if
(
sequence_number
==
0
)
if
(
sequence_number
==
0
)
{
s
->
dispose_op
=
APNG_DISPOSE_OP_BACKGROUND
;
if
(
s
->
dispose_op
==
APNG_DISPOSE_OP_PREVIOUS
)
{
av_log
(
avctx
,
AV_LOG_ERROR
,
"Dispose operation 'previous' is not yet implemented, using 'none'.
\n
"
);
s
->
dispose_op
=
APNG_DISPOSE_OP_NONE
;
s
->
frame_id
=
0
;
}
else
{
s
->
frame_id
++
;
if
(
s
->
frame_id
==
1
&&
s
->
dispose_op
==
APNG_DISPOSE_OP_PREVIOUS
)
/* previous for the second frame is the first frame */
s
->
dispose_op
=
APNG_DISPOSE_OP_NONE
;
}
return
0
;
...
...
@@ -864,8 +867,9 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
{
int
i
,
j
;
uint8_t
*
pd
=
p
->
data
[
0
];
/* TODO make pd_last point to the one before for APNG_DISPOSE_OP_PREVIOUS */
uint8_t
*
pd_last
=
s
->
last_picture
.
f
->
data
[
0
];
uint8_t
*
pd_last_region
=
s
->
dispose_op
==
APNG_DISPOSE_OP_PREVIOUS
?
s
->
previous_picture
.
f
->
data
[
0
]
:
s
->
last_picture
.
f
->
data
[
0
];
int
ls
=
FFMIN
(
av_image_get_linesize
(
p
->
format
,
s
->
width
,
0
),
s
->
width
*
s
->
bpp
);
if
(
s
->
blend_op
==
APNG_BLEND_OP_OVER
&&
...
...
@@ -876,6 +880,9 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
}
ff_thread_await_progress
(
&
s
->
last_picture
,
INT_MAX
,
0
);
if
(
s
->
dispose_op
==
APNG_DISPOSE_OP_PREVIOUS
)
ff_thread_await_progress
(
&
s
->
previous_picture
,
INT_MAX
,
0
);
for
(
j
=
0
;
j
<
s
->
y_offset
;
j
++
)
{
for
(
i
=
0
;
i
<
ls
;
i
++
)
pd
[
i
]
=
pd_last
[
i
];
...
...
@@ -886,6 +893,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
if
(
s
->
dispose_op
!=
APNG_DISPOSE_OP_BACKGROUND
&&
s
->
blend_op
==
APNG_BLEND_OP_OVER
)
{
uint8_t
ri
,
gi
,
bi
,
ai
;
pd_last_region
+=
s
->
y_offset
*
s
->
image_linesize
;
if
(
avctx
->
pix_fmt
==
AV_PIX_FMT_RGBA
)
{
ri
=
0
;
gi
=
1
;
...
...
@@ -907,17 +915,17 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
/* output = alpha * foreground + (1-alpha) * background */
switch
(
alpha
)
{
case
0
:
pd
[
i
+
ri
]
=
pd_last
[
i
+
ri
];
pd
[
i
+
gi
]
=
pd_last
[
i
+
gi
];
pd
[
i
+
bi
]
=
pd_last
[
i
+
bi
];
pd
[
i
+
ri
]
=
pd_last
_region
[
i
+
ri
];
pd
[
i
+
gi
]
=
pd_last
_region
[
i
+
gi
];
pd
[
i
+
bi
]
=
pd_last
_region
[
i
+
bi
];
pd
[
i
+
ai
]
=
0xff
;
break
;
case
255
:
break
;
default
:
pd
[
i
+
ri
]
=
FAST_DIV255
(
alpha
*
pd
[
i
+
ri
]
+
(
255
-
alpha
)
*
pd_last
[
i
+
ri
]);
pd
[
i
+
gi
]
=
FAST_DIV255
(
alpha
*
pd
[
i
+
gi
]
+
(
255
-
alpha
)
*
pd_last
[
i
+
gi
]);
pd
[
i
+
bi
]
=
FAST_DIV255
(
alpha
*
pd
[
i
+
bi
]
+
(
255
-
alpha
)
*
pd_last
[
i
+
bi
]);
pd
[
i
+
ri
]
=
FAST_DIV255
(
alpha
*
pd
[
i
+
ri
]
+
(
255
-
alpha
)
*
pd_last
_region
[
i
+
ri
]);
pd
[
i
+
gi
]
=
FAST_DIV255
(
alpha
*
pd
[
i
+
gi
]
+
(
255
-
alpha
)
*
pd_last
_region
[
i
+
gi
]);
pd
[
i
+
bi
]
=
FAST_DIV255
(
alpha
*
pd
[
i
+
bi
]
+
(
255
-
alpha
)
*
pd_last
_region
[
i
+
bi
]);
pd
[
i
+
ai
]
=
0xff
;
break
;
}
...
...
@@ -926,6 +934,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s,
pd
[
i
]
=
pd_last
[
i
];
pd
+=
s
->
image_linesize
;
pd_last
+=
s
->
image_linesize
;
pd_last_region
+=
s
->
image_linesize
;
}
}
else
{
for
(
j
=
s
->
y_offset
;
j
<
s
->
y_offset
+
s
->
cur_h
;
j
++
)
{
...
...
@@ -955,6 +964,7 @@ static int decode_frame_common(AVCodecContext *avctx, PNGDecContext *s,
uint32_t
tag
,
length
;
int
decode_next_dat
=
0
;
int
ret
=
AVERROR_INVALIDDATA
;
AVFrame
*
ref
;
for
(;;)
{
length
=
bytestream2_get_bytes_left
(
&
s
->
gb
);
...
...
@@ -1053,11 +1063,13 @@ exit_loop:
handle_small_bpp
(
s
,
p
);
/* handle p-frames only if a predecessor frame is available */
if
(
s
->
last_picture
.
f
->
data
[
0
])
{
ref
=
s
->
dispose_op
==
APNG_DISPOSE_OP_PREVIOUS
?
s
->
previous_picture
.
f
:
s
->
last_picture
.
f
;
if
(
ref
->
data
[
0
])
{
if
(
!
(
avpkt
->
flags
&
AV_PKT_FLAG_KEY
)
&&
avctx
->
codec_tag
!=
AV_RL32
(
"MPNG"
)
&&
s
->
last_picture
.
f
->
width
==
p
->
width
&&
s
->
last_picture
.
f
->
height
==
p
->
height
&&
s
->
last_picture
.
f
->
format
==
p
->
format
&&
re
f
->
width
==
p
->
width
&&
re
f
->
height
==
p
->
height
&&
re
f
->
format
==
p
->
format
)
{
if
(
CONFIG_PNG_DECODER
&&
avctx
->
codec_id
!=
AV_CODEC_ID_APNG
)
handle_p_frame_png
(
s
,
p
);
...
...
@@ -1141,9 +1153,13 @@ static int decode_frame_apng(AVCodecContext *avctx,
PNGDecContext
*
const
s
=
avctx
->
priv_data
;
int
ret
;
AVFrame
*
p
;
ThreadFrame
tmp
;
ff_thread_release_buffer
(
avctx
,
&
s
->
last_picture
);
FFSWAP
(
ThreadFrame
,
s
->
picture
,
s
->
last_picture
);
ff_thread_release_buffer
(
avctx
,
&
s
->
previous_picture
);
tmp
=
s
->
previous_picture
;
s
->
previous_picture
=
s
->
last_picture
;
s
->
last_picture
=
s
->
picture
;
s
->
picture
=
tmp
;
p
=
s
->
picture
.
f
;
if
(
!
(
s
->
state
&
PNG_IHDR
))
{
...
...
@@ -1193,13 +1209,22 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src)
{
PNGDecContext
*
psrc
=
src
->
priv_data
;
PNGDecContext
*
pdst
=
dst
->
priv_data
;
int
ret
;
if
(
dst
==
src
)
return
0
;
pdst
->
frame_id
=
psrc
->
frame_id
;
ff_thread_release_buffer
(
dst
,
&
pdst
->
picture
);
if
(
psrc
->
picture
.
f
->
data
[
0
])
return
ff_thread_ref_frame
(
&
pdst
->
picture
,
&
psrc
->
picture
);
if
(
psrc
->
picture
.
f
->
data
[
0
]
&&
(
ret
=
ff_thread_ref_frame
(
&
pdst
->
picture
,
&
psrc
->
picture
))
<
0
)
return
ret
;
if
(
CONFIG_APNG_DECODER
&&
dst
->
codec_id
==
AV_CODEC_ID_APNG
)
{
ff_thread_release_buffer
(
dst
,
&
pdst
->
last_picture
);
if
(
psrc
->
last_picture
.
f
->
data
[
0
])
return
ff_thread_ref_frame
(
&
pdst
->
last_picture
,
&
psrc
->
last_picture
);
}
return
0
;
}
...
...
@@ -1209,9 +1234,10 @@ static av_cold int png_dec_init(AVCodecContext *avctx)
PNGDecContext
*
s
=
avctx
->
priv_data
;
s
->
avctx
=
avctx
;
s
->
previous_picture
.
f
=
av_frame_alloc
();
s
->
last_picture
.
f
=
av_frame_alloc
();
s
->
picture
.
f
=
av_frame_alloc
();
if
(
!
s
->
last_picture
.
f
||
!
s
->
picture
.
f
)
if
(
!
s
->
previous_picture
.
f
||
!
s
->
last_picture
.
f
||
!
s
->
picture
.
f
)
return
AVERROR
(
ENOMEM
);
if
(
!
avctx
->
internal
->
is_copy
)
{
...
...
@@ -1226,6 +1252,8 @@ static av_cold int png_dec_end(AVCodecContext *avctx)
{
PNGDecContext
*
s
=
avctx
->
priv_data
;
ff_thread_release_buffer
(
avctx
,
&
s
->
previous_picture
);
av_frame_free
(
&
s
->
previous_picture
.
f
);
ff_thread_release_buffer
(
avctx
,
&
s
->
last_picture
);
av_frame_free
(
&
s
->
last_picture
.
f
);
ff_thread_release_buffer
(
avctx
,
&
s
->
picture
);
...
...
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