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