Unified · Split
| @@ -38,6 +38,7 @@ typedef struct PNGDecContext { · 37 unmodified lines | |||
| 38 | AVCodecContext *avctx; | 38 | AVCodecContext *avctx; |
| 39 | 39 | ||
| 40 | GetByteContext gb; | 40 | GetByteContext gb; |
| 41 | ThreadFrame previous_picture; | ||
| 41 | ThreadFrame last_picture; | 42 | ThreadFrame last_picture; |
| 42 | ThreadFrame picture; | 43 | ThreadFrame picture; |
| 43 | 44 | ||
| @@ -55,6 +56,7 @@ typedef struct PNGDecContext { · 11 unmodified lines | |||
| 55 | int bits_per_pixel; | 56 | int bits_per_pixel; |
| 56 | int bpp; | 57 | int bpp; |
| 57 | 58 | ||
| 59 | int frame_id; | ||
| 58 | uint8_t *image_buf; | 60 | uint8_t *image_buf; |
| 59 | int image_linesize; | 61 | int image_linesize; |
| 60 | uint32_t palette[256]; | 62 | uint32_t palette[256]; |
| @@ -827,13 +829,14 @@ static int decode_fctl_chunk(AVCodecContext *avctx, PNGDecContext *s, · 766 unmodified lines | |||
| 827 | return AVERROR_INVALIDDATA; | 829 | return AVERROR_INVALIDDATA; |
| 828 | 830 | ||
| 829 | /* always (re)start with a clean frame */ | 831 | /* always (re)start with a clean frame */ |
| 830 | if (sequence_number == 0) | 832 | if (sequence_number == 0) { |
| 831 | s->dispose_op = APNG_DISPOSE_OP_BACKGROUND; | 833 | s->dispose_op = APNG_DISPOSE_OP_BACKGROUND; |
| 832 | 834 | s->frame_id = 0; | |
| 833 | if (s->dispose_op == APNG_DISPOSE_OP_PREVIOUS) { | 835 | } else { |
| 834 | av_log(avctx, AV_LOG_ERROR, | 836 | s->frame_id++; |
| 835 | "Dispose operation 'previous' is not yet implemented, using 'none'.\n"); | 837 | if (s->frame_id == 1 && s->dispose_op == APNG_DISPOSE_OP_PREVIOUS) |
| 836 | s->dispose_op = APNG_DISPOSE_OP_NONE; | 838 | /* previous for the second frame is the first frame */ |
| 839 | s->dispose_op = APNG_DISPOSE_OP_NONE; | ||
| 837 | } | 840 | } |
| 838 | 841 | ||
| 839 | return 0; | 842 | return 0; |
| @@ -864,8 +867,9 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, · 24 unmodified lines | |||
| 864 | { | 867 | { |
| 865 | int i, j; | 868 | int i, j; |
| 866 | uint8_t *pd = p->data[0]; | 869 | uint8_t *pd = p->data[0]; |
| 867 | /* TODO make pd_last point to the one before for APNG_DISPOSE_OP_PREVIOUS */ | ||
| 868 | uint8_t *pd_last = s->last_picture.f->data[0]; | 870 | uint8_t *pd_last = s->last_picture.f->data[0]; |
| 871 | uint8_t *pd_last_region = s->dispose_op == APNG_DISPOSE_OP_PREVIOUS ? | ||
| 872 | s->previous_picture.f->data[0] : s->last_picture.f->data[0]; | ||
| 869 | int ls = FFMIN(av_image_get_linesize(p->format, s->width, 0), s->width * s->bpp); | 873 | int ls = FFMIN(av_image_get_linesize(p->format, s->width, 0), s->width * s->bpp); |
| 870 | 874 | ||
| 871 | if (s->blend_op == APNG_BLEND_OP_OVER && | 875 | if (s->blend_op == APNG_BLEND_OP_OVER && |
| @@ -876,6 +880,9 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, · 4 unmodified lines | |||
| 876 | } | 880 | } |
| 877 | 881 | ||
| 878 | ff_thread_await_progress(&s->last_picture, INT_MAX, 0); | 882 | ff_thread_await_progress(&s->last_picture, INT_MAX, 0); |
| 883 | if (s->dispose_op == APNG_DISPOSE_OP_PREVIOUS) | ||
| 884 | ff_thread_await_progress(&s->previous_picture, INT_MAX, 0); | ||
| 885 | |||
| 879 | for (j = 0; j < s->y_offset; j++) { | 886 | for (j = 0; j < s->y_offset; j++) { |
| 880 | for (i = 0; i < ls; i++) | 887 | for (i = 0; i < ls; i++) |
| 881 | pd[i] = pd_last[i]; | 888 | pd[i] = pd_last[i]; |
| @@ -886,6 +893,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, · 4 unmodified lines | |||
| 886 | if (s->dispose_op != APNG_DISPOSE_OP_BACKGROUND && s->blend_op == APNG_BLEND_OP_OVER) { | 893 | if (s->dispose_op != APNG_DISPOSE_OP_BACKGROUND && s->blend_op == APNG_BLEND_OP_OVER) { |
| 887 | uint8_t ri, gi, bi, ai; | 894 | uint8_t ri, gi, bi, ai; |
| 888 | 895 | ||
| 896 | pd_last_region += s->y_offset * s->image_linesize; | ||
| 889 | if (avctx->pix_fmt == AV_PIX_FMT_RGBA) { | 897 | if (avctx->pix_fmt == AV_PIX_FMT_RGBA) { |
| 890 | ri = 0; | 898 | ri = 0; |
| 891 | gi = 1; | 899 | gi = 1; |
| @@ -907,17 +915,17 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, · 15 unmodified lines | |||
| 907 | /* output = alpha * foreground + (1-alpha) * background */ | 915 | /* output = alpha * foreground + (1-alpha) * background */ |
| 908 | switch (alpha) { | 916 | switch (alpha) { |
| 909 | case 0: | 917 | case 0: |
| 910 | pd[i+ri] = pd_last[i+ri]; | 918 | pd[i+ri] = pd_last_region[i+ri]; |
| 911 | pd[i+gi] = pd_last[i+gi]; | 919 | pd[i+gi] = pd_last_region[i+gi]; |
| 912 | pd[i+bi] = pd_last[i+bi]; | 920 | pd[i+bi] = pd_last_region[i+bi]; |
| 913 | pd[i+ai] = 0xff; | 921 | pd[i+ai] = 0xff; |
| 914 | break; | 922 | break; |
| 915 | case 255: | 923 | case 255: |
| 916 | break; | 924 | break; |
| 917 | default: | 925 | default: |
| 918 | pd[i+ri] = FAST_DIV255(alpha * pd[i+ri] + (255 - alpha) * pd_last[i+ri]); | 926 | pd[i+ri] = FAST_DIV255(alpha * pd[i+ri] + (255 - alpha) * pd_last_region[i+ri]); |
| 919 | pd[i+gi] = FAST_DIV255(alpha * pd[i+gi] + (255 - alpha) * pd_last[i+gi]); | 927 | pd[i+gi] = FAST_DIV255(alpha * pd[i+gi] + (255 - alpha) * pd_last_region[i+gi]); |
| 920 | pd[i+bi] = FAST_DIV255(alpha * pd[i+bi] + (255 - alpha) * pd_last[i+bi]); | 928 | pd[i+bi] = FAST_DIV255(alpha * pd[i+bi] + (255 - alpha) * pd_last_region[i+bi]); |
| 921 | pd[i+ai] = 0xff; | 929 | pd[i+ai] = 0xff; |
| 922 | break; | 930 | break; |
| 923 | } | 931 | } |
| @@ -926,6 +934,7 @@ static int handle_p_frame_apng(AVCodecContext *avctx, PNGDecContext *s, · 2 unmodified lines | |||
| 926 | pd[i] = pd_last[i]; | 934 | pd[i] = pd_last[i]; |
| 927 | pd += s->image_linesize; | 935 | pd += s->image_linesize; |
| 928 | pd_last += s->image_linesize; | 936 | pd_last += s->image_linesize; |
| 937 | pd_last_region += s->image_linesize; | ||
| 929 | } | 938 | } |
| 930 | } else { | 939 | } else { |
| 931 | for (j = s->y_offset; j < s->y_offset + s->cur_h; j++) { | 940 | 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, · 23 unmodified lines | |||
| 955 | uint32_t tag, length; | 964 | uint32_t tag, length; |
| 956 | int decode_next_dat = 0; | 965 | int decode_next_dat = 0; |
| 957 | int ret = AVERROR_INVALIDDATA; | 966 | int ret = AVERROR_INVALIDDATA; |
| 967 | AVFrame *ref; | ||
| 958 | 968 | ||
| 959 | for (;;) { | 969 | for (;;) { |
| 960 | length = bytestream2_get_bytes_left(&s->gb); | 970 | length = bytestream2_get_bytes_left(&s->gb); |
| @@ -1053,11 +1063,13 @@ exit_loop: · 92 unmodified lines | |||
| 1053 | handle_small_bpp(s, p); | 1063 | handle_small_bpp(s, p); |
| 1054 | 1064 | ||
| 1055 | /* handle p-frames only if a predecessor frame is available */ | 1065 | /* handle p-frames only if a predecessor frame is available */ |
| 1056 | if (s->last_picture.f->data[0]) { | 1066 | ref = s->dispose_op == APNG_DISPOSE_OP_PREVIOUS ? |
| 1067 | s->previous_picture.f : s->last_picture.f; | ||
| 1068 | if (ref->data[0]) { | ||
| 1057 | if ( !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG") | 1069 | if ( !(avpkt->flags & AV_PKT_FLAG_KEY) && avctx->codec_tag != AV_RL32("MPNG") |
| 1058 | && s->last_picture.f->width == p->width | 1070 | && ref->width == p->width |
| 1059 | && s->last_picture.f->height== p->height | 1071 | && ref->height== p->height |
| 1060 | && s->last_picture.f->format== p->format | 1072 | && ref->format== p->format |
| 1061 | ) { | 1073 | ) { |
| 1062 | if (CONFIG_PNG_DECODER && avctx->codec_id != AV_CODEC_ID_APNG) | 1074 | if (CONFIG_PNG_DECODER && avctx->codec_id != AV_CODEC_ID_APNG) |
| 1063 | handle_p_frame_png(s, p); | 1075 | handle_p_frame_png(s, p); |
| @@ -1141,9 +1153,13 @@ static int decode_frame_apng(AVCodecContext *avctx, · 77 unmodified lines | |||
| 1141 | PNGDecContext *const s = avctx->priv_data; | 1153 | PNGDecContext *const s = avctx->priv_data; |
| 1142 | int ret; | 1154 | int ret; |
| 1143 | AVFrame *p; | 1155 | AVFrame *p; |
| 1156 | ThreadFrame tmp; | ||
| 1144 | 1157 | ||
| 1145 | ff_thread_release_buffer(avctx, &s->last_picture); | 1158 | ff_thread_release_buffer(avctx, &s->previous_picture); |
| 1146 | FFSWAP(ThreadFrame, s->picture, s->last_picture); | 1159 | tmp = s->previous_picture; |
| 1160 | s->previous_picture = s->last_picture; | ||
| 1161 | s->last_picture = s->picture; | ||
| 1162 | s->picture = tmp; | ||
| 1147 | p = s->picture.f; | 1163 | p = s->picture.f; |
| 1148 | 1164 | ||
| 1149 | if (!(s->state & PNG_IHDR)) { | 1165 | if (!(s->state & PNG_IHDR)) { |
| @@ -1193,13 +1209,22 @@ static int update_thread_context(AVCodecContext *dst, const AVCodecContext *src) · 43 unmodified lines | |||
| 1193 | { | 1209 | { |
| 1194 | PNGDecContext *psrc = src->priv_data; | 1210 | PNGDecContext *psrc = src->priv_data; |
| 1195 | PNGDecContext *pdst = dst->priv_data; | 1211 | PNGDecContext *pdst = dst->priv_data; |
| 1212 | int ret; | ||
| 1196 | 1213 | ||
| 1197 | if (dst == src) | 1214 | if (dst == src) |
| 1198 | return 0; | 1215 | return 0; |
| 1199 | 1216 | ||
| 1217 | pdst->frame_id = psrc->frame_id; | ||
| 1218 | |||
| 1200 | ff_thread_release_buffer(dst, &pdst->picture); | 1219 | ff_thread_release_buffer(dst, &pdst->picture); |
| 1201 | if (psrc->picture.f->data[0]) | 1220 | if (psrc->picture.f->data[0] && |
| 1202 | return ff_thread_ref_frame(&pdst->picture, &psrc->picture); | 1221 | (ret = ff_thread_ref_frame(&pdst->picture, &psrc->picture)) < 0) |
| 1222 | return ret; | ||
| 1223 | if (CONFIG_APNG_DECODER && dst->codec_id == AV_CODEC_ID_APNG) { | ||
| 1224 | ff_thread_release_buffer(dst, &pdst->last_picture); | ||
| 1225 | if (psrc->last_picture.f->data[0]) | ||
| 1226 | return ff_thread_ref_frame(&pdst->last_picture, &psrc->last_picture); | ||
| 1227 | } | ||
| 1203 | 1228 | ||
| 1204 | return 0; | 1229 | return 0; |
| 1205 | } | 1230 | } |
| @@ -1209,9 +1234,10 @@ static av_cold int png_dec_init(AVCodecContext *avctx) · 3 unmodified lines | |||
| 1209 | PNGDecContext *s = avctx->priv_data; | 1234 | PNGDecContext *s = avctx->priv_data; |
| 1210 | 1235 | ||
| 1211 | s->avctx = avctx; | 1236 | s->avctx = avctx; |
| 1237 | s->previous_picture.f = av_frame_alloc(); | ||
| 1212 | s->last_picture.f = av_frame_alloc(); | 1238 | s->last_picture.f = av_frame_alloc(); |
| 1213 | s->picture.f = av_frame_alloc(); | 1239 | s->picture.f = av_frame_alloc(); |
| 1214 | if (!s->last_picture.f || !s->picture.f) | 1240 | if (!s->previous_picture.f || !s->last_picture.f || !s->picture.f) |
| 1215 | return AVERROR(ENOMEM); | 1241 | return AVERROR(ENOMEM); |
| 1216 | 1242 | ||
| 1217 | if (!avctx->internal->is_copy) { | 1243 | if (!avctx->internal->is_copy) { |
| @@ -1226,6 +1252,8 @@ static av_cold int png_dec_end(AVCodecContext *avctx) · 8 unmodified lines | |||
| 1226 | { | 1252 | { |
| 1227 | PNGDecContext *s = avctx->priv_data; | 1253 | PNGDecContext *s = avctx->priv_data; |
| 1228 | 1254 | ||
| 1255 | ff_thread_release_buffer(avctx, &s->previous_picture); | ||
| 1256 | av_frame_free(&s->previous_picture.f); | ||
| 1229 | ff_thread_release_buffer(avctx, &s->last_picture); | 1257 | ff_thread_release_buffer(avctx, &s->last_picture); |
| 1230 | av_frame_free(&s->last_picture.f); | 1258 | av_frame_free(&s->last_picture.f); |
| 1231 | ff_thread_release_buffer(avctx, &s->picture); | 1259 | ff_thread_release_buffer(avctx, &s->picture); |