From 3c7e97343065fc728dbdba27c1c1abd41847bd12 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 2 Nov 2018 01:33:08 +0100 Subject: [PATCH 001/153] Update for 4.1 Signed-off-by: Michael Niedermayer --- RELEASE | 2 +- doc/Doxyfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASE b/RELEASE index ff2c9d1a30b72..7d5c902e77790 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -4.0.git +4.1 diff --git a/doc/Doxyfile b/doc/Doxyfile index 0891899505ce1..452057c46b11d 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = +PROJECT_NUMBER = 4.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From 1665ac6a446190c24c4875e2bab6f76132f7b05c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 2 Nov 2018 01:36:21 +0100 Subject: [PATCH 002/153] RELEASE_NOTES: Based on the version from 4.0 Signed-off-by: Michael Niedermayer --- RELEASE_NOTES | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 RELEASE_NOTES diff --git a/RELEASE_NOTES b/RELEASE_NOTES new file mode 100644 index 0000000000000..a24c9e6f4484f --- /dev/null +++ b/RELEASE_NOTES @@ -0,0 +1,15 @@ + + ┌─────────────────────────────────────────────┐ + │ RELEASE NOTES for FFmpeg 4.1 "al-Khwarizmi" │ + └─────────────────────────────────────────────┘ + + The FFmpeg Project proudly presents FFmpeg 4.1 "al-Khwarizmi", about 6 + months after the release of FFmpeg 4.0. + + A complete Changelog is available at the root of the project, and the + complete Git history on https://git.ffmpeg.org/gitweb/ffmpeg.git + + We hope you will like this release as much as we enjoyed working on it, and + as usual, if you have any questions about it, or any FFmpeg related topic, + feel free to join us on the #ffmpeg IRC channel (on irc.freenode.net) or ask + on the mailing-lists. From 5060a615c7389808a4006e2d3e9acb9562d6ebec Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Tue, 30 Oct 2018 14:38:41 +0000 Subject: [PATCH 003/153] fate/api-h264-slice-test: don't use ssize_t Fixes ticket #7521 Signed-off-by: James Almer (cherry picked from commit 8096f52049acb1861645815a54435b9fd2d5e77a) --- tests/api/api-h264-slice-test.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c index 57e7dc79c3dc1..e68fa6e2526ba 100644 --- a/tests/api/api-h264-slice-test.c +++ b/tests/api/api-h264-slice-test.c @@ -180,15 +180,12 @@ int main(int argc, char **argv) while(1) { uint16_t size = 0; - ssize_t ret = fread(&size, 1, sizeof(uint16_t), fd); - if (ret < 0) { - perror("Couldn't read size"); - exit(1); - } else if (ret != sizeof(uint16_t)) + size_t ret = fread(&size, 1, sizeof(uint16_t), fd); + if (ret != sizeof(uint16_t)) break; size = ntohs(size); ret = fread(p, 1, size, fd); - if (ret < 0 || ret != size) { + if (ret != size) { perror("Couldn't read data"); exit(1); } From 765fb1f224f61c563d3c82cfefbe44f43d452290 Mon Sep 17 00:00:00 2001 From: Josh de Kock Date: Tue, 30 Oct 2018 14:38:42 +0000 Subject: [PATCH 004/153] fate/api-h264-slice-test: use cleaner error handling Signed-off-by: James Almer (cherry picked from commit 1052578dadf72e400cee5ad2ad5dce899032d362) --- tests/api/api-h264-slice-test.c | 79 ++++++++++++++++++++------------- 1 file changed, 47 insertions(+), 32 deletions(-) diff --git a/tests/api/api-h264-slice-test.c b/tests/api/api-h264-slice-test.c index e68fa6e2526ba..be03e80049a5b 100644 --- a/tests/api/api-h264-slice-test.c +++ b/tests/api/api-h264-slice-test.c @@ -48,7 +48,7 @@ static int header = 0; -static void decode(AVCodecContext *dec_ctx, AVFrame *frame, +static int decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt) { static uint64_t frame_cnt = 0; @@ -57,20 +57,20 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame, ret = avcodec_send_packet(dec_ctx, pkt); if (ret < 0) { fprintf(stderr, "Error sending a packet for decoding: %s\n", av_err2str(ret)); - exit(1); + return ret; } while (ret >= 0) { const AVPixFmtDescriptor *desc; - char *sum; + char sum[AV_HASH_MAX_SIZE * 2 + 1]; struct AVHashContext *hash; ret = avcodec_receive_frame(dec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { - return; + return 0; } else if (ret < 0) { fprintf(stderr, "Error during decoding: %s\n", av_err2str(ret)); - exit(1); + return ret; } if (!header) { @@ -87,9 +87,10 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame, header = 1; } desc = av_pix_fmt_desc_get(dec_ctx->pix_fmt); - av_hash_alloc(&hash, "md5"); + if ((ret = av_hash_alloc(&hash, "md5")) < 0) { + return ret; + } av_hash_init(hash); - sum = av_mallocz(av_hash_get_size(hash) * 2 + 1); for (int i = 0; i < frame->height; i++) av_hash_update(hash, &frame->data[0][i * frame->linesize[0]], frame->width); @@ -104,25 +105,25 @@ static void decode(AVCodecContext *dec_ctx, AVFrame *frame, (frame->width * frame->height + 2 * (frame->height >> desc->log2_chroma_h) * (frame->width >> desc->log2_chroma_w)), sum); frame_cnt += 1; av_hash_freep(&hash); - av_free(sum); } + return 0; } int main(int argc, char **argv) { - const AVCodec *codec; + const AVCodec *codec = NULL; AVCodecContext *c = NULL; - AVFrame *frame; + AVFrame *frame = NULL; unsigned int threads; AVPacket *pkt; - FILE *fd; + FILE *file = NULL; char nal[MAX_SLICES * UINT16_MAX + AV_INPUT_BUFFER_PADDING_SIZE]; - int nals = 0; + int nals = 0, ret = 0; char *p = nal; if (argc < 4) { fprintf(stderr, "Usage: %s \n", argv[0]); - exit(1); + return -1; } if (!(threads = strtoul(argv[1], NULL, 0))) @@ -134,17 +135,20 @@ int main(int argc, char **argv) setmode(fileno(stdout), O_BINARY); #endif - if (!(pkt = av_packet_alloc())) - exit(1); + if (!(pkt = av_packet_alloc())) { + return -1; + } if (!(codec = avcodec_find_decoder(AV_CODEC_ID_H264))) { fprintf(stderr, "Codec not found\n"); - exit(1); + ret = -1; + goto err; } if (!(c = avcodec_alloc_context3(codec))) { fprintf(stderr, "Could not allocate video codec context\n"); - exit(1); + ret = -1; + goto err; } c->width = 352; @@ -154,15 +158,16 @@ int main(int argc, char **argv) c->thread_type = FF_THREAD_SLICE; c->thread_count = threads; - if (avcodec_open2(c, codec, NULL) < 0) { + if ((ret = avcodec_open2(c, codec, NULL)) < 0) { fprintf(stderr, "Could not open codec\n"); - exit(1); + goto err; } #if HAVE_THREADS if (c->active_thread_type != FF_THREAD_SLICE) { fprintf(stderr, "Couldn't activate slice threading: %d\n", c->active_thread_type); - exit(1); + ret = -1; + goto err; } #else fprintf(stderr, "WARN: not using threads, only checking decoding slice NALUs\n"); @@ -170,31 +175,37 @@ int main(int argc, char **argv) if (!(frame = av_frame_alloc())) { fprintf(stderr, "Could not allocate video frame\n"); - exit(1); + ret = -1; + goto err; } - if (!(fd = fopen(argv[2], "rb"))) { + if (!(file = fopen(argv[2], "rb"))) { fprintf(stderr, "Couldn't open NALU file: %s\n", argv[2]); - exit(1); + ret = -1; + goto err; } while(1) { uint16_t size = 0; - size_t ret = fread(&size, 1, sizeof(uint16_t), fd); + size_t ret = fread(&size, 1, sizeof(uint16_t), file); if (ret != sizeof(uint16_t)) break; + size = ntohs(size); - ret = fread(p, 1, size, fd); + ret = fread(p, 1, size, file); if (ret != size) { perror("Couldn't read data"); - exit(1); + goto err; } p += ret; if (++nals >= threads) { + int decret = 0; pkt->data = nal; pkt->size = p - nal; - decode(c, frame, pkt); + if ((decret = decode(c, frame, pkt)) < 0) { + goto err; + } memset(nal, 0, MAX_SLICES * UINT16_MAX + AV_INPUT_BUFFER_PADDING_SIZE); nals = 0; p = nal; @@ -204,15 +215,19 @@ int main(int argc, char **argv) if (nals) { pkt->data = nal; pkt->size = p - nal; - decode(c, frame, pkt); + if ((ret = decode(c, frame, pkt)) < 0) { + goto err; + } } - decode(c, frame, NULL); + ret = decode(c, frame, NULL); - fclose(fd); - avcodec_free_context(&c); +err: + if (file) + fclose(file); av_frame_free(&frame); + avcodec_free_context(&c); av_packet_free(&pkt); - return 0; + return ret; } From 041231fcd632a33506689e44e5b45f29ac4ce050 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Wed, 24 Oct 2018 11:52:42 -0700 Subject: [PATCH 005/153] libavfilter/vf_yadif: Make frame management logic and options shareable I'm writing a cuda implementation of yadif, and while this obviously has a very different implementation of the actual filtering, all the frame management is unchanged. To avoid duplicating that logic, let's make it shareable. From the perspective of the existing filter, the only real change is introducing a function pointer for the filter() function so it can be specified for the specific filter. (cherry picked from commit 598f0f39271d6033588b4d8ccc672c5bdc85fec7) --- libavfilter/Makefile | 2 +- libavfilter/vf_yadif.c | 196 ++-------------------------------- libavfilter/yadif.h | 9 ++ libavfilter/yadif_common.c | 209 +++++++++++++++++++++++++++++++++++++ 4 files changed, 228 insertions(+), 188 deletions(-) create mode 100644 libavfilter/yadif_common.c diff --git a/libavfilter/Makefile b/libavfilter/Makefile index c35cd8f4220d7..ffbcb40806b4c 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -407,7 +407,7 @@ OBJS-$(CONFIG_WAVEFORM_FILTER) += vf_waveform.o OBJS-$(CONFIG_WEAVE_FILTER) += vf_weave.o OBJS-$(CONFIG_XBR_FILTER) += vf_xbr.o OBJS-$(CONFIG_XSTACK_FILTER) += vf_stack.o framesync.o -OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o +OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o yadif_common.o OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_ZOOMPAN_FILTER) += vf_zoompan.o OBJS-$(CONFIG_ZSCALE_FILTER) += vf_zscale.o diff --git a/libavfilter/vf_yadif.c b/libavfilter/vf_yadif.c index f58d8ac2bce32..3107924932a51 100644 --- a/libavfilter/vf_yadif.c +++ b/libavfilter/vf_yadif.c @@ -22,7 +22,6 @@ #include "libavutil/avassert.h" #include "libavutil/cpu.h" #include "libavutil/common.h" -#include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "libavutil/imgutils.h" #include "avfilter.h" @@ -254,166 +253,6 @@ static void filter(AVFilterContext *ctx, AVFrame *dstpic, emms_c(); } -static int return_frame(AVFilterContext *ctx, int is_second) -{ - YADIFContext *yadif = ctx->priv; - AVFilterLink *link = ctx->outputs[0]; - int tff, ret; - - if (yadif->parity == -1) { - tff = yadif->cur->interlaced_frame ? - yadif->cur->top_field_first : 1; - } else { - tff = yadif->parity ^ 1; - } - - if (is_second) { - yadif->out = ff_get_video_buffer(link, link->w, link->h); - if (!yadif->out) - return AVERROR(ENOMEM); - - av_frame_copy_props(yadif->out, yadif->cur); - yadif->out->interlaced_frame = 0; - } - - filter(ctx, yadif->out, tff ^ !is_second, tff); - - if (is_second) { - int64_t cur_pts = yadif->cur->pts; - int64_t next_pts = yadif->next->pts; - - if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) { - yadif->out->pts = cur_pts + next_pts; - } else { - yadif->out->pts = AV_NOPTS_VALUE; - } - } - ret = ff_filter_frame(ctx->outputs[0], yadif->out); - - yadif->frame_pending = (yadif->mode&1) && !is_second; - return ret; -} - -static int checkstride(YADIFContext *yadif, const AVFrame *a, const AVFrame *b) -{ - int i; - for (i = 0; i < yadif->csp->nb_components; i++) - if (a->linesize[i] != b->linesize[i]) - return 1; - return 0; -} - -static void fixstride(AVFilterLink *link, AVFrame *f) -{ - AVFrame *dst = ff_default_get_video_buffer(link, f->width, f->height); - if(!dst) - return; - av_frame_copy_props(dst, f); - av_image_copy(dst->data, dst->linesize, - (const uint8_t **)f->data, f->linesize, - dst->format, dst->width, dst->height); - av_frame_unref(f); - av_frame_move_ref(f, dst); - av_frame_free(&dst); -} - -static int filter_frame(AVFilterLink *link, AVFrame *frame) -{ - AVFilterContext *ctx = link->dst; - YADIFContext *yadif = ctx->priv; - - av_assert0(frame); - - if (yadif->frame_pending) - return_frame(ctx, 1); - - if (yadif->prev) - av_frame_free(&yadif->prev); - yadif->prev = yadif->cur; - yadif->cur = yadif->next; - yadif->next = frame; - - if (!yadif->cur && - !(yadif->cur = av_frame_clone(yadif->next))) - return AVERROR(ENOMEM); - - if (checkstride(yadif, yadif->next, yadif->cur)) { - av_log(ctx, AV_LOG_VERBOSE, "Reallocating frame due to differing stride\n"); - fixstride(link, yadif->next); - } - if (checkstride(yadif, yadif->next, yadif->cur)) - fixstride(link, yadif->cur); - if (yadif->prev && checkstride(yadif, yadif->next, yadif->prev)) - fixstride(link, yadif->prev); - if (checkstride(yadif, yadif->next, yadif->cur) || (yadif->prev && checkstride(yadif, yadif->next, yadif->prev))) { - av_log(ctx, AV_LOG_ERROR, "Failed to reallocate frame\n"); - return -1; - } - - if (!yadif->prev) - return 0; - - if ((yadif->deint && !yadif->cur->interlaced_frame) || - ctx->is_disabled || - (yadif->deint && !yadif->prev->interlaced_frame && yadif->prev->repeat_pict) || - (yadif->deint && !yadif->next->interlaced_frame && yadif->next->repeat_pict) - ) { - yadif->out = av_frame_clone(yadif->cur); - if (!yadif->out) - return AVERROR(ENOMEM); - - av_frame_free(&yadif->prev); - if (yadif->out->pts != AV_NOPTS_VALUE) - yadif->out->pts *= 2; - return ff_filter_frame(ctx->outputs[0], yadif->out); - } - - yadif->out = ff_get_video_buffer(ctx->outputs[0], link->w, link->h); - if (!yadif->out) - return AVERROR(ENOMEM); - - av_frame_copy_props(yadif->out, yadif->cur); - yadif->out->interlaced_frame = 0; - - if (yadif->out->pts != AV_NOPTS_VALUE) - yadif->out->pts *= 2; - - return return_frame(ctx, 0); -} - -static int request_frame(AVFilterLink *link) -{ - AVFilterContext *ctx = link->src; - YADIFContext *yadif = ctx->priv; - int ret; - - if (yadif->frame_pending) { - return_frame(ctx, 1); - return 0; - } - - if (yadif->eof) - return AVERROR_EOF; - - ret = ff_request_frame(ctx->inputs[0]); - - if (ret == AVERROR_EOF && yadif->cur) { - AVFrame *next = av_frame_clone(yadif->next); - - if (!next) - return AVERROR(ENOMEM); - - next->pts = yadif->next->pts * 2 - yadif->cur->pts; - - filter_frame(ctx->inputs[0], next); - yadif->eof = 1; - } else if (ret < 0) { - return ret; - } - - return 0; -} - static av_cold void uninit(AVFilterContext *ctx) { YADIFContext *yadif = ctx->priv; @@ -492,6 +331,7 @@ static int config_props(AVFilterLink *link) } s->csp = av_pix_fmt_desc_get(link->format); + s->filter = filter; if (s->csp->comp[0].depth > 8) { s->filter_line = filter_line_c_16bit; s->filter_edges = filter_edges_16bit; @@ -507,37 +347,19 @@ static int config_props(AVFilterLink *link) } -#define OFFSET(x) offsetof(YADIFContext, x) -#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM - -#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit } - -static const AVOption yadif_options[] = { - { "mode", "specify the interlacing mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=YADIF_MODE_SEND_FRAME}, 0, 3, FLAGS, "mode"}, - CONST("send_frame", "send one frame for each frame", YADIF_MODE_SEND_FRAME, "mode"), - CONST("send_field", "send one frame for each field", YADIF_MODE_SEND_FIELD, "mode"), - CONST("send_frame_nospatial", "send one frame for each frame, but skip spatial interlacing check", YADIF_MODE_SEND_FRAME_NOSPATIAL, "mode"), - CONST("send_field_nospatial", "send one frame for each field, but skip spatial interlacing check", YADIF_MODE_SEND_FIELD_NOSPATIAL, "mode"), - - { "parity", "specify the assumed picture field parity", OFFSET(parity), AV_OPT_TYPE_INT, {.i64=YADIF_PARITY_AUTO}, -1, 1, FLAGS, "parity" }, - CONST("tff", "assume top field first", YADIF_PARITY_TFF, "parity"), - CONST("bff", "assume bottom field first", YADIF_PARITY_BFF, "parity"), - CONST("auto", "auto detect parity", YADIF_PARITY_AUTO, "parity"), - - { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=YADIF_DEINT_ALL}, 0, 1, FLAGS, "deint" }, - CONST("all", "deinterlace all frames", YADIF_DEINT_ALL, "deint"), - CONST("interlaced", "only deinterlace frames marked as interlaced", YADIF_DEINT_INTERLACED, "deint"), - - { NULL } +static const AVClass yadif_class = { + .class_name = "yadif", + .item_name = av_default_item_name, + .option = ff_yadif_options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_FILTER, }; -AVFILTER_DEFINE_CLASS(yadif); - static const AVFilterPad avfilter_vf_yadif_inputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .filter_frame = filter_frame, + .filter_frame = ff_yadif_filter_frame, }, { NULL } }; @@ -546,7 +368,7 @@ static const AVFilterPad avfilter_vf_yadif_outputs[] = { { .name = "default", .type = AVMEDIA_TYPE_VIDEO, - .request_frame = request_frame, + .request_frame = ff_yadif_request_frame, .config_props = config_props, }, { NULL } diff --git a/libavfilter/yadif.h b/libavfilter/yadif.h index d23d1380d0089..32d6f4a0d4080 100644 --- a/libavfilter/yadif.h +++ b/libavfilter/yadif.h @@ -19,6 +19,7 @@ #ifndef AVFILTER_YADIF_H #define AVFILTER_YADIF_H +#include "libavutil/opt.h" #include "libavutil/pixdesc.h" #include "avfilter.h" @@ -54,6 +55,8 @@ typedef struct YADIFContext { AVFrame *prev; AVFrame *out; + void (*filter)(AVFilterContext *ctx, AVFrame *dstpic, int parity, int tff); + /** * Required alignment for filter_line */ @@ -71,4 +74,10 @@ typedef struct YADIFContext { void ff_yadif_init_x86(YADIFContext *yadif); +int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame); + +int ff_yadif_request_frame(AVFilterLink *link); + +extern const AVOption ff_yadif_options[]; + #endif /* AVFILTER_YADIF_H */ diff --git a/libavfilter/yadif_common.c b/libavfilter/yadif_common.c new file mode 100644 index 0000000000000..19e8ac5281923 --- /dev/null +++ b/libavfilter/yadif_common.c @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2006-2011 Michael Niedermayer + * 2010 James Darnley + + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "libavutil/avassert.h" +#include "libavutil/imgutils.h" +#include "internal.h" +#include "yadif.h" + +static int return_frame(AVFilterContext *ctx, int is_second) +{ + YADIFContext *yadif = ctx->priv; + AVFilterLink *link = ctx->outputs[0]; + int tff, ret; + + if (yadif->parity == -1) { + tff = yadif->cur->interlaced_frame ? + yadif->cur->top_field_first : 1; + } else { + tff = yadif->parity ^ 1; + } + + if (is_second) { + yadif->out = ff_get_video_buffer(link, link->w, link->h); + if (!yadif->out) + return AVERROR(ENOMEM); + + av_frame_copy_props(yadif->out, yadif->cur); + yadif->out->interlaced_frame = 0; + } + + yadif->filter(ctx, yadif->out, tff ^ !is_second, tff); + + if (is_second) { + int64_t cur_pts = yadif->cur->pts; + int64_t next_pts = yadif->next->pts; + + if (next_pts != AV_NOPTS_VALUE && cur_pts != AV_NOPTS_VALUE) { + yadif->out->pts = cur_pts + next_pts; + } else { + yadif->out->pts = AV_NOPTS_VALUE; + } + } + ret = ff_filter_frame(ctx->outputs[0], yadif->out); + + yadif->frame_pending = (yadif->mode&1) && !is_second; + return ret; +} + +static int checkstride(YADIFContext *yadif, const AVFrame *a, const AVFrame *b) +{ + int i; + for (i = 0; i < yadif->csp->nb_components; i++) + if (a->linesize[i] != b->linesize[i]) + return 1; + return 0; +} + +static void fixstride(AVFilterLink *link, AVFrame *f) +{ + AVFrame *dst = ff_default_get_video_buffer(link, f->width, f->height); + if(!dst) + return; + av_frame_copy_props(dst, f); + av_image_copy(dst->data, dst->linesize, + (const uint8_t **)f->data, f->linesize, + dst->format, dst->width, dst->height); + av_frame_unref(f); + av_frame_move_ref(f, dst); + av_frame_free(&dst); +} + +int ff_yadif_filter_frame(AVFilterLink *link, AVFrame *frame) +{ + AVFilterContext *ctx = link->dst; + YADIFContext *yadif = ctx->priv; + + av_assert0(frame); + + if (yadif->frame_pending) + return_frame(ctx, 1); + + if (yadif->prev) + av_frame_free(&yadif->prev); + yadif->prev = yadif->cur; + yadif->cur = yadif->next; + yadif->next = frame; + + if (!yadif->cur && + !(yadif->cur = av_frame_clone(yadif->next))) + return AVERROR(ENOMEM); + + if (checkstride(yadif, yadif->next, yadif->cur)) { + av_log(ctx, AV_LOG_VERBOSE, "Reallocating frame due to differing stride\n"); + fixstride(link, yadif->next); + } + if (checkstride(yadif, yadif->next, yadif->cur)) + fixstride(link, yadif->cur); + if (yadif->prev && checkstride(yadif, yadif->next, yadif->prev)) + fixstride(link, yadif->prev); + if (checkstride(yadif, yadif->next, yadif->cur) || (yadif->prev && checkstride(yadif, yadif->next, yadif->prev))) { + av_log(ctx, AV_LOG_ERROR, "Failed to reallocate frame\n"); + return -1; + } + + if (!yadif->prev) + return 0; + + if ((yadif->deint && !yadif->cur->interlaced_frame) || + ctx->is_disabled || + (yadif->deint && !yadif->prev->interlaced_frame && yadif->prev->repeat_pict) || + (yadif->deint && !yadif->next->interlaced_frame && yadif->next->repeat_pict) + ) { + yadif->out = av_frame_clone(yadif->cur); + if (!yadif->out) + return AVERROR(ENOMEM); + + av_frame_free(&yadif->prev); + if (yadif->out->pts != AV_NOPTS_VALUE) + yadif->out->pts *= 2; + return ff_filter_frame(ctx->outputs[0], yadif->out); + } + + yadif->out = ff_get_video_buffer(ctx->outputs[0], link->w, link->h); + if (!yadif->out) + return AVERROR(ENOMEM); + + av_frame_copy_props(yadif->out, yadif->cur); + yadif->out->interlaced_frame = 0; + + if (yadif->out->pts != AV_NOPTS_VALUE) + yadif->out->pts *= 2; + + return return_frame(ctx, 0); +} + +int ff_yadif_request_frame(AVFilterLink *link) +{ + AVFilterContext *ctx = link->src; + YADIFContext *yadif = ctx->priv; + int ret; + + if (yadif->frame_pending) { + return_frame(ctx, 1); + return 0; + } + + if (yadif->eof) + return AVERROR_EOF; + + ret = ff_request_frame(ctx->inputs[0]); + + if (ret == AVERROR_EOF && yadif->cur) { + AVFrame *next = av_frame_clone(yadif->next); + + if (!next) + return AVERROR(ENOMEM); + + next->pts = yadif->next->pts * 2 - yadif->cur->pts; + + ff_yadif_filter_frame(ctx->inputs[0], next); + yadif->eof = 1; + } else if (ret < 0) { + return ret; + } + + return 0; +} + +#define OFFSET(x) offsetof(YADIFContext, x) +#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM + +#define CONST(name, help, val, unit) { name, help, 0, AV_OPT_TYPE_CONST, {.i64=val}, INT_MIN, INT_MAX, FLAGS, unit } + +const AVOption ff_yadif_options[] = { + { "mode", "specify the interlacing mode", OFFSET(mode), AV_OPT_TYPE_INT, {.i64=YADIF_MODE_SEND_FRAME}, 0, 3, FLAGS, "mode"}, + CONST("send_frame", "send one frame for each frame", YADIF_MODE_SEND_FRAME, "mode"), + CONST("send_field", "send one frame for each field", YADIF_MODE_SEND_FIELD, "mode"), + CONST("send_frame_nospatial", "send one frame for each frame, but skip spatial interlacing check", YADIF_MODE_SEND_FRAME_NOSPATIAL, "mode"), + CONST("send_field_nospatial", "send one frame for each field, but skip spatial interlacing check", YADIF_MODE_SEND_FIELD_NOSPATIAL, "mode"), + + { "parity", "specify the assumed picture field parity", OFFSET(parity), AV_OPT_TYPE_INT, {.i64=YADIF_PARITY_AUTO}, -1, 1, FLAGS, "parity" }, + CONST("tff", "assume top field first", YADIF_PARITY_TFF, "parity"), + CONST("bff", "assume bottom field first", YADIF_PARITY_BFF, "parity"), + CONST("auto", "auto detect parity", YADIF_PARITY_AUTO, "parity"), + + { "deint", "specify which frames to deinterlace", OFFSET(deint), AV_OPT_TYPE_INT, {.i64=YADIF_DEINT_ALL}, 0, 1, FLAGS, "deint" }, + CONST("all", "deinterlace all frames", YADIF_DEINT_ALL, "deint"), + CONST("interlaced", "only deinterlace frames marked as interlaced", YADIF_DEINT_INTERLACED, "deint"), + + { NULL } +}; From 67126555fc030e465806a84084e710f20c8a4775 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Sun, 21 Oct 2018 13:49:16 -0700 Subject: [PATCH 006/153] avfilter/vf_yadif_cuda: CUDA accelerated yadif deinterlacer This is a cuda implementation of yadif, which gives us a way to do deinterlacing when using the nvdec hwaccel. In that scenario we don't have access to the nvidia deinterlacer. (cherry picked from commit d5272e94ab22bfc8f01fa3174e2c4664161ddf5a) --- Changelog | 1 + configure | 1 + doc/filters.texi | 58 +++++ libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/version.h | 2 +- libavfilter/vf_yadif_cuda.c | 426 +++++++++++++++++++++++++++++++++++ libavfilter/vf_yadif_cuda.cu | 296 ++++++++++++++++++++++++ 8 files changed, 785 insertions(+), 1 deletion(-) create mode 100644 libavfilter/vf_yadif_cuda.c create mode 100644 libavfilter/vf_yadif_cuda.cu diff --git a/Changelog b/Changelog index 36c00b456af01..97ea8e12c3107 100644 --- a/Changelog +++ b/Changelog @@ -42,6 +42,7 @@ version 4.1: - xstack filter - pcm vidc decoder and encoder - (a)graphmonitor filter +- yadif_cuda filter version 4.0: diff --git a/configure b/configure index 01c3a1011d428..5a5d0b0868fdf 100755 --- a/configure +++ b/configure @@ -3481,6 +3481,7 @@ zscale_filter_deps="libzimg const_nan" scale_vaapi_filter_deps="vaapi" vpp_qsv_filter_deps="libmfx" vpp_qsv_filter_select="qsvvpp" +yadif_cuda_filter_deps="cuda_sdk" # examples avio_dir_cmd_deps="avformat avutil" diff --git a/doc/filters.texi b/doc/filters.texi index 4345a4931b0b5..5d4bfd2e8e08c 100644 --- a/doc/filters.texi +++ b/doc/filters.texi @@ -17943,6 +17943,64 @@ filter"). It accepts the following parameters: +@table @option + +@item mode +The interlacing mode to adopt. It accepts one of the following values: + +@table @option +@item 0, send_frame +Output one frame for each frame. +@item 1, send_field +Output one frame for each field. +@item 2, send_frame_nospatial +Like @code{send_frame}, but it skips the spatial interlacing check. +@item 3, send_field_nospatial +Like @code{send_field}, but it skips the spatial interlacing check. +@end table + +The default value is @code{send_frame}. + +@item parity +The picture field parity assumed for the input interlaced video. It accepts one +of the following values: + +@table @option +@item 0, tff +Assume the top field is first. +@item 1, bff +Assume the bottom field is first. +@item -1, auto +Enable automatic detection of field parity. +@end table + +The default value is @code{auto}. +If the interlacing is unknown or the decoder does not export this information, +top field first will be assumed. + +@item deint +Specify which frames to deinterlace. Accept one of the following +values: + +@table @option +@item 0, all +Deinterlace all frames. +@item 1, interlaced +Only deinterlace frames marked as interlaced. +@end table + +The default value is @code{all}. +@end table + +@section yadif_cuda + +Deinterlace the input video using the @ref{yadif} algorithm, but implemented +in CUDA so that it can work as part of a GPU accelerated pipeline with nvdec +and/or nvenc. + +It accepts the following parameters: + + @table @option @item mode diff --git a/libavfilter/Makefile b/libavfilter/Makefile index ffbcb40806b4c..4b78b29fada8e 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -408,6 +408,7 @@ OBJS-$(CONFIG_WEAVE_FILTER) += vf_weave.o OBJS-$(CONFIG_XBR_FILTER) += vf_xbr.o OBJS-$(CONFIG_XSTACK_FILTER) += vf_stack.o framesync.o OBJS-$(CONFIG_YADIF_FILTER) += vf_yadif.o yadif_common.o +OBJS-$(CONFIG_YADIF_CUDA_FILTER) += vf_yadif_cuda.o vf_yadif_cuda.ptx.o yadif_common.o OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_ZOOMPAN_FILTER) += vf_zoompan.o OBJS-$(CONFIG_ZSCALE_FILTER) += vf_zscale.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index d5a211bda5919..c40c7e3a3c51a 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -389,6 +389,7 @@ extern AVFilter ff_vf_weave; extern AVFilter ff_vf_xbr; extern AVFilter ff_vf_xstack; extern AVFilter ff_vf_yadif; +extern AVFilter ff_vf_yadif_cuda; extern AVFilter ff_vf_zmq; extern AVFilter ff_vf_zoompan; extern AVFilter ff_vf_zscale; diff --git a/libavfilter/version.h b/libavfilter/version.h index 91c37509b4b52..9f0a9966eb8f1 100644 --- a/libavfilter/version.h +++ b/libavfilter/version.h @@ -31,7 +31,7 @@ #define LIBAVFILTER_VERSION_MAJOR 7 #define LIBAVFILTER_VERSION_MINOR 40 -#define LIBAVFILTER_VERSION_MICRO 100 +#define LIBAVFILTER_VERSION_MICRO 101 #define LIBAVFILTER_VERSION_INT AV_VERSION_INT(LIBAVFILTER_VERSION_MAJOR, \ LIBAVFILTER_VERSION_MINOR, \ diff --git a/libavfilter/vf_yadif_cuda.c b/libavfilter/vf_yadif_cuda.c new file mode 100644 index 0000000000000..be22344d9de22 --- /dev/null +++ b/libavfilter/vf_yadif_cuda.c @@ -0,0 +1,426 @@ +/* + * Copyright (C) 2018 Philip Langdale + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include "libavutil/avassert.h" +#include "libavutil/hwcontext_cuda.h" +#include "internal.h" +#include "yadif.h" + +extern char vf_yadif_cuda_ptx[]; + +typedef struct DeintCUDAContext { + YADIFContext yadif; + + AVCUDADeviceContext *hwctx; + AVBufferRef *device_ref; + AVBufferRef *input_frames_ref; + AVHWFramesContext *input_frames; + + CUcontext cu_ctx; + CUstream stream; + CUmodule cu_module; + CUfunction cu_func_uchar; + CUfunction cu_func_uchar2; + CUfunction cu_func_ushort; + CUfunction cu_func_ushort2; +} DeintCUDAContext; + +#define DIV_UP(a, b) ( ((a) + (b) - 1) / (b) ) +#define ALIGN_UP(a, b) (((a) + (b) - 1) & ~((b) - 1)) +#define BLOCKX 32 +#define BLOCKY 16 + +static int check_cu(AVFilterContext *avctx, CUresult err, const char *func) +{ + const char *err_name; + const char *err_string; + + av_log(avctx, AV_LOG_TRACE, "Calling %s\n", func); + + if (err == CUDA_SUCCESS) + return 0; + + cuGetErrorName(err, &err_name); + cuGetErrorString(err, &err_string); + + av_log(avctx, AV_LOG_ERROR, "%s failed", func); + if (err_name && err_string) + av_log(avctx, AV_LOG_ERROR, " -> %s: %s", err_name, err_string); + av_log(avctx, AV_LOG_ERROR, "\n"); + + return AVERROR_EXTERNAL; +} + +#define CHECK_CU(x) check_cu(ctx, (x), #x) + +static CUresult call_kernel(AVFilterContext *ctx, CUfunction func, + CUdeviceptr prev, CUdeviceptr cur, CUdeviceptr next, + CUarray_format format, int channels, + int src_width, // Width is pixels per channel + int src_height, // Height is pixels per channel + int src_pitch, // Pitch is bytes + CUdeviceptr dst, + int dst_width, // Width is pixels per channel + int dst_height, // Height is pixels per channel + int dst_pitch, // Pitch is pixels per channel + int parity, int tff) +{ + DeintCUDAContext *s = ctx->priv; + CUtexObject tex_prev = 0, tex_cur = 0, tex_next = 0; + CUresult err; + int skip_spatial_check = s->yadif.mode&2; + + void *args[] = { &dst, &tex_prev, &tex_cur, &tex_next, + &dst_width, &dst_height, &dst_pitch, + &src_width, &src_height, &parity, &tff, + &skip_spatial_check }; + + CUDA_TEXTURE_DESC tex_desc = { + .filterMode = CU_TR_FILTER_MODE_POINT, + .flags = CU_TRSF_READ_AS_INTEGER, + }; + + CUDA_RESOURCE_DESC res_desc = { + .resType = CU_RESOURCE_TYPE_PITCH2D, + .res.pitch2D.format = format, + .res.pitch2D.numChannels = channels, + .res.pitch2D.width = src_width, + .res.pitch2D.height = src_height, + .res.pitch2D.pitchInBytes = src_pitch, + }; + + res_desc.res.pitch2D.devPtr = (CUdeviceptr)prev; + err = CHECK_CU(cuTexObjectCreate(&tex_prev, &res_desc, &tex_desc, NULL)); + if (err != CUDA_SUCCESS) { + goto exit; + } + + res_desc.res.pitch2D.devPtr = (CUdeviceptr)cur; + err = CHECK_CU(cuTexObjectCreate(&tex_cur, &res_desc, &tex_desc, NULL)); + if (err != CUDA_SUCCESS) { + goto exit; + } + + res_desc.res.pitch2D.devPtr = (CUdeviceptr)next; + err = CHECK_CU(cuTexObjectCreate(&tex_next, &res_desc, &tex_desc, NULL)); + if (err != CUDA_SUCCESS) { + goto exit; + } + + err = CHECK_CU(cuLaunchKernel(func, + DIV_UP(dst_width, BLOCKX), DIV_UP(dst_height, BLOCKY), 1, + BLOCKX, BLOCKY, 1, + 0, s->stream, args, NULL)); + +exit: + if (tex_prev) + CHECK_CU(cuTexObjectDestroy(tex_prev)); + if (tex_cur) + CHECK_CU(cuTexObjectDestroy(tex_cur)); + if (tex_next) + CHECK_CU(cuTexObjectDestroy(tex_next)); + + return err; +} + +static void filter(AVFilterContext *ctx, AVFrame *dst, + int parity, int tff) +{ + DeintCUDAContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + CUcontext dummy; + CUresult err; + int i; + + err = CHECK_CU(cuCtxPushCurrent(s->cu_ctx)); + if (err != CUDA_SUCCESS) { + goto exit; + } + + for (i = 0; i < y->csp->nb_components; i++) { + CUfunction func; + CUarray_format format; + int pixel_size, channels; + const AVComponentDescriptor *comp = &y->csp->comp[i]; + + if (comp->plane < i) { + // We process planes as a whole, so don't reprocess + // them for additional components + continue; + } + + pixel_size = (comp->depth + comp->shift) / 8; + channels = comp->step / pixel_size; + if (pixel_size > 2 || channels > 2) { + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + switch (pixel_size) { + case 1: + func = channels == 1 ? s->cu_func_uchar : s->cu_func_uchar2; + format = CU_AD_FORMAT_UNSIGNED_INT8; + break; + case 2: + func = channels == 1 ? s->cu_func_ushort : s->cu_func_ushort2; + format = CU_AD_FORMAT_UNSIGNED_INT16; + break; + default: + av_log(ctx, AV_LOG_ERROR, "Unsupported pixel format: %s\n", y->csp->name); + goto exit; + } + av_log(ctx, AV_LOG_TRACE, + "Deinterlacing plane %d: pixel_size: %d channels: %d\n", + comp->plane, pixel_size, channels); + call_kernel(ctx, func, + (CUdeviceptr)y->prev->data[i], + (CUdeviceptr)y->cur->data[i], + (CUdeviceptr)y->next->data[i], + format, channels, + AV_CEIL_RSHIFT(y->cur->width, i ? y->csp->log2_chroma_w : 0), + AV_CEIL_RSHIFT(y->cur->height, i ? y->csp->log2_chroma_h : 0), + y->cur->linesize[i], + (CUdeviceptr)dst->data[i], + AV_CEIL_RSHIFT(dst->width, i ? y->csp->log2_chroma_w : 0), + AV_CEIL_RSHIFT(dst->height, i ? y->csp->log2_chroma_h : 0), + dst->linesize[i] / comp->step, + parity, tff); + } + + err = CHECK_CU(cuStreamSynchronize(s->stream)); + if (err != CUDA_SUCCESS) { + goto exit; + } + +exit: + CHECK_CU(cuCtxPopCurrent(&dummy)); + return; +} + +static av_cold void deint_cuda_uninit(AVFilterContext *ctx) +{ + CUcontext dummy; + DeintCUDAContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + + if (s->cu_module) { + CHECK_CU(cuCtxPushCurrent(s->cu_ctx)); + CHECK_CU(cuModuleUnload(s->cu_module)); + CHECK_CU(cuCtxPopCurrent(&dummy)); + } + + av_frame_free(&y->prev); + av_frame_free(&y->cur); + av_frame_free(&y->next); + + av_buffer_unref(&s->device_ref); + s->hwctx = NULL; + av_buffer_unref(&s->input_frames_ref); + s->input_frames = NULL; +} + +static int deint_cuda_query_formats(AVFilterContext *ctx) +{ + enum AVPixelFormat pix_fmts[] = { + AV_PIX_FMT_CUDA, AV_PIX_FMT_NONE, + }; + int ret; + + if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), + &ctx->inputs[0]->out_formats)) < 0) + return ret; + if ((ret = ff_formats_ref(ff_make_format_list(pix_fmts), + &ctx->outputs[0]->in_formats)) < 0) + return ret; + + return 0; +} + +static int config_input(AVFilterLink *inlink) +{ + AVFilterContext *ctx = inlink->dst; + DeintCUDAContext *s = ctx->priv; + + if (!inlink->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "A hardware frames reference is " + "required to associate the processing device.\n"); + return AVERROR(EINVAL); + } + + s->input_frames_ref = av_buffer_ref(inlink->hw_frames_ctx); + if (!s->input_frames_ref) { + av_log(ctx, AV_LOG_ERROR, "A input frames reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + s->input_frames = (AVHWFramesContext*)s->input_frames_ref->data; + + return 0; +} + +static int config_output(AVFilterLink *link) +{ + AVHWFramesContext *output_frames; + AVFilterContext *ctx = link->src; + DeintCUDAContext *s = ctx->priv; + YADIFContext *y = &s->yadif; + int ret = 0; + CUcontext dummy; + CUresult err; + + av_assert0(s->input_frames); + s->device_ref = av_buffer_ref(s->input_frames->device_ref); + if (!s->device_ref) { + av_log(ctx, AV_LOG_ERROR, "A device reference create " + "failed.\n"); + return AVERROR(ENOMEM); + } + s->hwctx = ((AVHWDeviceContext*)s->device_ref->data)->hwctx; + s->cu_ctx = s->hwctx->cuda_ctx; + s->stream = s->hwctx->stream; + + link->hw_frames_ctx = av_hwframe_ctx_alloc(s->device_ref); + if (!link->hw_frames_ctx) { + av_log(ctx, AV_LOG_ERROR, "Failed to create HW frame context " + "for output.\n"); + ret = AVERROR(ENOMEM); + goto exit; + } + + output_frames = (AVHWFramesContext*)link->hw_frames_ctx->data; + + output_frames->format = AV_PIX_FMT_CUDA; + output_frames->sw_format = s->input_frames->sw_format; + output_frames->width = ctx->inputs[0]->w; + output_frames->height = ctx->inputs[0]->h; + + output_frames->initial_pool_size = 4; + + ret = ff_filter_init_hw_frames(ctx, link, 10); + if (ret < 0) + goto exit; + + ret = av_hwframe_ctx_init(link->hw_frames_ctx); + if (ret < 0) { + av_log(ctx, AV_LOG_ERROR, "Failed to initialise CUDA frame " + "context for output: %d\n", ret); + goto exit; + } + + link->time_base.num = ctx->inputs[0]->time_base.num; + link->time_base.den = ctx->inputs[0]->time_base.den * 2; + link->w = ctx->inputs[0]->w; + link->h = ctx->inputs[0]->h; + + if(y->mode & 1) + link->frame_rate = av_mul_q(ctx->inputs[0]->frame_rate, + (AVRational){2, 1}); + + if (link->w < 3 || link->h < 3) { + av_log(ctx, AV_LOG_ERROR, "Video of less than 3 columns or lines is not supported\n"); + ret = AVERROR(EINVAL); + goto exit; + } + + y->csp = av_pix_fmt_desc_get(output_frames->sw_format); + y->filter = filter; + + err = CHECK_CU(cuCtxPushCurrent(s->cu_ctx)); + if (err != CUDA_SUCCESS) { + ret = AVERROR_EXTERNAL; + goto exit; + } + + err = CHECK_CU(cuModuleLoadData(&s->cu_module, vf_yadif_cuda_ptx)); + if (err != CUDA_SUCCESS) { + ret = AVERROR_INVALIDDATA; + goto exit; + } + + err = CHECK_CU(cuModuleGetFunction(&s->cu_func_uchar, s->cu_module, "yadif_uchar")); + if (err != CUDA_SUCCESS) { + ret = AVERROR_INVALIDDATA; + goto exit; + } + + err = CHECK_CU(cuModuleGetFunction(&s->cu_func_uchar2, s->cu_module, "yadif_uchar2")); + if (err != CUDA_SUCCESS) { + ret = AVERROR_INVALIDDATA; + goto exit; + } + + err= CHECK_CU(cuModuleGetFunction(&s->cu_func_ushort, s->cu_module, "yadif_ushort")); + if (err != CUDA_SUCCESS) { + ret = AVERROR_INVALIDDATA; + goto exit; + } + + err = CHECK_CU(cuModuleGetFunction(&s->cu_func_ushort2, s->cu_module, "yadif_ushort2")); + if (err != CUDA_SUCCESS) { + ret = AVERROR_INVALIDDATA; + goto exit; + } + +exit: + CHECK_CU(cuCtxPopCurrent(&dummy)); + + return ret; +} + +static const AVClass yadif_cuda_class = { + .class_name = "yadif_cuda", + .item_name = av_default_item_name, + .option = ff_yadif_options, + .version = LIBAVUTIL_VERSION_INT, + .category = AV_CLASS_CATEGORY_FILTER, +}; + +static const AVFilterPad deint_cuda_inputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .filter_frame = ff_yadif_filter_frame, + .config_props = config_input, + }, + { NULL } +}; + +static const AVFilterPad deint_cuda_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .request_frame = ff_yadif_request_frame, + .config_props = config_output, + }, + { NULL } +}; + +AVFilter ff_vf_yadif_cuda = { + .name = "yadif_cuda", + .description = NULL_IF_CONFIG_SMALL("Deinterlace CUDA frames"), + .priv_size = sizeof(DeintCUDAContext), + .priv_class = &yadif_cuda_class, + .uninit = deint_cuda_uninit, + .query_formats = deint_cuda_query_formats, + .inputs = deint_cuda_inputs, + .outputs = deint_cuda_outputs, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL, + .flags_internal = FF_FILTER_FLAG_HWFRAME_AWARE, +}; diff --git a/libavfilter/vf_yadif_cuda.cu b/libavfilter/vf_yadif_cuda.cu new file mode 100644 index 0000000000000..65a902c66b234 --- /dev/null +++ b/libavfilter/vf_yadif_cuda.cu @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2018 Philip Langdale + * + * This file is part of FFmpeg. + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +template +__inline__ __device__ T spatial_predictor(T a, T b, T c, T d, T e, T f, T g, + T h, T i, T j, T k, T l, T m, T n) +{ + int spatial_pred = (d + k)/2; + int spatial_score = abs(c - j) + abs(d - k) + abs(e - l); + + int score = abs(b - k) + abs(c - l) + abs(d - m); + if (score < spatial_score) { + spatial_pred = (c + l)/2; + spatial_score = score; + score = abs(a - l) + abs(b - m) + abs(c - n); + if (score < spatial_score) { + spatial_pred = (b + m)/2; + spatial_score = score; + } + } + score = abs(d - i) + abs(e - j) + abs(f - k); + if (score < spatial_score) { + spatial_pred = (e + j)/2; + spatial_score = score; + score = abs(e - h) + abs(f - i) + abs(g - j); + if (score < spatial_score) { + spatial_pred = (f + i)/2; + spatial_score = score; + } + } + return spatial_pred; +} + +__inline__ __device__ int max3(int a, int b, int c) +{ + int x = max(a, b); + return max(x, c); +} + +__inline__ __device__ int min3(int a, int b, int c) +{ + int x = min(a, b); + return min(x, c); +} + +template +__inline__ __device__ T temporal_predictor(T A, T B, T C, T D, T E, T F, + T G, T H, T I, T J, T K, T L, + T spatial_pred, bool skip_check) +{ + int p0 = (C + H) / 2; + int p1 = F; + int p2 = (D + I) / 2; + int p3 = G; + int p4 = (E + J) / 2; + + int tdiff0 = abs(D - I); + int tdiff1 = (abs(A - F) + abs(B - G)) / 2; + int tdiff2 = (abs(K - F) + abs(G - L)) / 2; + + int diff = max3(tdiff0, tdiff1, tdiff2); + + if (!skip_check) { + int maxi = max3(p2 - p3, p2 - p1, min(p0 - p1, p4 - p3)); + int mini = min3(p2 - p3, p2 - p1, max(p0 - p1, p4 - p3)); + diff = max3(diff, mini, -maxi); + } + + if (spatial_pred > p2 + diff) { + spatial_pred = p2 + diff; + } + if (spatial_pred < p2 - diff) { + spatial_pred = p2 - diff; + } + + return spatial_pred; +} + +template +__inline__ __device__ void yadif_single(T *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, bool skip_spatial_check) +{ + // Identify location + int xo = blockIdx.x * blockDim.x + threadIdx.x; + int yo = blockIdx.y * blockDim.y + threadIdx.y; + + if (xo >= dst_width || yo >= dst_height) { + return; + } + + // Don't modify the primary field + if (yo % 2 == parity) { + dst[yo*dst_pitch+xo] = tex2D(cur, xo, yo); + return; + } + + // Calculate spatial prediction + T a = tex2D(cur, xo - 3, yo - 1); + T b = tex2D(cur, xo - 2, yo - 1); + T c = tex2D(cur, xo - 1, yo - 1); + T d = tex2D(cur, xo - 0, yo - 1); + T e = tex2D(cur, xo + 1, yo - 1); + T f = tex2D(cur, xo + 2, yo - 1); + T g = tex2D(cur, xo + 3, yo - 1); + + T h = tex2D(cur, xo - 3, yo + 1); + T i = tex2D(cur, xo - 2, yo + 1); + T j = tex2D(cur, xo - 1, yo + 1); + T k = tex2D(cur, xo - 0, yo + 1); + T l = tex2D(cur, xo + 1, yo + 1); + T m = tex2D(cur, xo + 2, yo + 1); + T n = tex2D(cur, xo + 3, yo + 1); + + T spatial_pred = + spatial_predictor(a, b, c, d, e, f, g, h, i, j, k, l, m, n); + + // Calculate temporal prediction + int is_second_field = !(parity ^ tff); + + cudaTextureObject_t prev2 = prev; + cudaTextureObject_t prev1 = is_second_field ? cur : prev; + cudaTextureObject_t next1 = is_second_field ? next : cur; + cudaTextureObject_t next2 = next; + + T A = tex2D(prev2, xo, yo - 1); + T B = tex2D(prev2, xo, yo + 1); + T C = tex2D(prev1, xo, yo - 2); + T D = tex2D(prev1, xo, yo + 0); + T E = tex2D(prev1, xo, yo + 2); + T F = tex2D(cur, xo, yo - 1); + T G = tex2D(cur, xo, yo + 1); + T H = tex2D(next1, xo, yo - 2); + T I = tex2D(next1, xo, yo + 0); + T J = tex2D(next1, xo, yo + 2); + T K = tex2D(next2, xo, yo - 1); + T L = tex2D(next2, xo, yo + 1); + + spatial_pred = temporal_predictor(A, B, C, D, E, F, G, H, I, J, K, L, + spatial_pred, skip_spatial_check); + + dst[yo*dst_pitch+xo] = spatial_pred; +} + +template +__inline__ __device__ void yadif_double(T *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, bool skip_spatial_check) +{ + int xo = blockIdx.x * blockDim.x + threadIdx.x; + int yo = blockIdx.y * blockDim.y + threadIdx.y; + + if (xo >= dst_width || yo >= dst_height) { + return; + } + + if (yo % 2 == parity) { + // Don't modify the primary field + dst[yo*dst_pitch+xo] = tex2D(cur, xo, yo); + return; + } + + T a = tex2D(cur, xo - 3, yo - 1); + T b = tex2D(cur, xo - 2, yo - 1); + T c = tex2D(cur, xo - 1, yo - 1); + T d = tex2D(cur, xo - 0, yo - 1); + T e = tex2D(cur, xo + 1, yo - 1); + T f = tex2D(cur, xo + 2, yo - 1); + T g = tex2D(cur, xo + 3, yo - 1); + + T h = tex2D(cur, xo - 3, yo + 1); + T i = tex2D(cur, xo - 2, yo + 1); + T j = tex2D(cur, xo - 1, yo + 1); + T k = tex2D(cur, xo - 0, yo + 1); + T l = tex2D(cur, xo + 1, yo + 1); + T m = tex2D(cur, xo + 2, yo + 1); + T n = tex2D(cur, xo + 3, yo + 1); + + T spatial_pred = { + spatial_predictor(a.x, b.x, c.x, d.x, e.x, f.x, g.x, h.x, i.x, j.x, k.x, l.x, m.x, n.x), + spatial_predictor(a.y, b.y, c.y, d.y, e.y, f.y, g.y, h.y, i.y, j.y, k.y, l.y, m.y, n.y) }; + + // Calculate temporal prediction + int is_second_field = !(parity ^ tff); + + cudaTextureObject_t prev2 = prev; + cudaTextureObject_t prev1 = is_second_field ? cur : prev; + cudaTextureObject_t next1 = is_second_field ? next : cur; + cudaTextureObject_t next2 = next; + + T A = tex2D(prev2, xo, yo - 1); + T B = tex2D(prev2, xo, yo + 1); + T C = tex2D(prev1, xo, yo - 2); + T D = tex2D(prev1, xo, yo + 0); + T E = tex2D(prev1, xo, yo + 2); + T F = tex2D(cur, xo, yo - 1); + T G = tex2D(cur, xo, yo + 1); + T H = tex2D(next1, xo, yo - 2); + T I = tex2D(next1, xo, yo + 0); + T J = tex2D(next1, xo, yo + 2); + T K = tex2D(next2, xo, yo - 1); + T L = tex2D(next2, xo, yo + 1); + + spatial_pred = { + temporal_predictor(A.x, B.x, C.x, D.x, E.x, F.x, G.x, H.x, I.x, J.x, K.x, L.x, + spatial_pred.x, skip_spatial_check), + temporal_predictor(A.y, B.y, C.y, D.y, E.y, F.y, G.y, H.y, I.y, J.y, K.y, L.y, + spatial_pred.y, skip_spatial_check) }; + + dst[yo*dst_pitch+xo] = spatial_pred; +} + +extern "C" { + +__global__ void yadif_uchar(unsigned char *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, bool skip_spatial_check) +{ + yadif_single(dst, prev, cur, next, + dst_width, dst_height, dst_pitch, + src_width, src_height, + parity, tff, skip_spatial_check); +} + +__global__ void yadif_ushort(unsigned short *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, bool skip_spatial_check) +{ + yadif_single(dst, prev, cur, next, + dst_width, dst_height, dst_pitch, + src_width, src_height, + parity, tff, skip_spatial_check); +} + +__global__ void yadif_uchar2(uchar2 *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, bool skip_spatial_check) +{ + yadif_double(dst, prev, cur, next, + dst_width, dst_height, dst_pitch, + src_width, src_height, + parity, tff, skip_spatial_check); +} + +__global__ void yadif_ushort2(ushort2 *dst, + cudaTextureObject_t prev, + cudaTextureObject_t cur, + cudaTextureObject_t next, + int dst_width, int dst_height, int dst_pitch, + int src_width, int src_height, + int parity, int tff, bool skip_spatial_check) +{ + yadif_double(dst, prev, cur, next, + dst_width, dst_height, dst_pitch, + src_width, src_height, + parity, tff, skip_spatial_check); +} + +} /* extern "C" */ From 6feec11e489b729a0ed7ead205e2aca6837d5f20 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Wed, 24 Oct 2018 18:38:44 -0700 Subject: [PATCH 007/153] avcodec/nvdec: Increase frame pool size to help deinterlacing With the cuda yadif filter in use, the number of mapped decoder frames could increase by two, as the filter holds on to additional frames. (cherry picked from commit 1b41115ef70896d9b98ce842dc5f21c465396ce2) --- libavcodec/nvdec.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvdec.c b/libavcodec/nvdec.c index 4dd6b1acf3ade..0426c9b3197f8 100644 --- a/libavcodec/nvdec.c +++ b/libavcodec/nvdec.c @@ -601,7 +601,11 @@ int ff_nvdec_frame_params(AVCodecContext *avctx, frames_ctx->format = AV_PIX_FMT_CUDA; frames_ctx->width = (avctx->coded_width + 1) & ~1; frames_ctx->height = (avctx->coded_height + 1) & ~1; - frames_ctx->initial_pool_size = dpb_size; + /* + * We add two extra frames to the pool to account for deinterlacing filters + * holding onto their frames. + */ + frames_ctx->initial_pool_size = dpb_size + 2; frames_ctx->free = nvdec_free_dummy; frames_ctx->pool = av_buffer_pool_init(0, nvdec_alloc_dummy); From ebc1c49e417cf7d7096d7a038d1e3e61f0432f19 Mon Sep 17 00:00:00 2001 From: Philip Langdale Date: Fri, 2 Nov 2018 14:08:18 -0700 Subject: [PATCH 008/153] avfilter/vf_cuda_yadif: Avoid new syntax for vector initialisation This requires a newer version of CUDA than we want to require. (cherry picked from commit 8e50215b5e02074b0773dfcf55867654ee59c179) --- libavfilter/vf_yadif_cuda.cu | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/libavfilter/vf_yadif_cuda.cu b/libavfilter/vf_yadif_cuda.cu index 65a902c66b234..12e7e4a443cea 100644 --- a/libavfilter/vf_yadif_cuda.cu +++ b/libavfilter/vf_yadif_cuda.cu @@ -201,9 +201,11 @@ __inline__ __device__ void yadif_double(T *dst, T m = tex2D(cur, xo + 2, yo + 1); T n = tex2D(cur, xo + 3, yo + 1); - T spatial_pred = { - spatial_predictor(a.x, b.x, c.x, d.x, e.x, f.x, g.x, h.x, i.x, j.x, k.x, l.x, m.x, n.x), - spatial_predictor(a.y, b.y, c.y, d.y, e.y, f.y, g.y, h.y, i.y, j.y, k.y, l.y, m.y, n.y) }; + T spatial_pred; + spatial_pred.x = + spatial_predictor(a.x, b.x, c.x, d.x, e.x, f.x, g.x, h.x, i.x, j.x, k.x, l.x, m.x, n.x); + spatial_pred.y = + spatial_predictor(a.y, b.y, c.y, d.y, e.y, f.y, g.y, h.y, i.y, j.y, k.y, l.y, m.y, n.y); // Calculate temporal prediction int is_second_field = !(parity ^ tff); @@ -226,11 +228,12 @@ __inline__ __device__ void yadif_double(T *dst, T K = tex2D(next2, xo, yo - 1); T L = tex2D(next2, xo, yo + 1); - spatial_pred = { + spatial_pred.x = temporal_predictor(A.x, B.x, C.x, D.x, E.x, F.x, G.x, H.x, I.x, J.x, K.x, L.x, - spatial_pred.x, skip_spatial_check), + spatial_pred.x, skip_spatial_check); + spatial_pred.y = temporal_predictor(A.y, B.y, C.y, D.y, E.y, F.y, G.y, H.y, I.y, J.y, K.y, L.y, - spatial_pred.y, skip_spatial_check) }; + spatial_pred.y, skip_spatial_check); dst[yo*dst_pitch+xo] = spatial_pred; } From b9875b75837dc75ba65254f1cdb0be50b1037d2d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Oct 2018 03:06:59 +0100 Subject: [PATCH 009/153] avcodec/prosumer: Check for bytestream eof in decompress() Fixes: Infinite loop Fixes: 10685/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PROSUMER_fuzzer-5652236881887232 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 9acdf17b2c30c44e6e6a3d3b3c22989b7e1117c3) Signed-off-by: Michael Niedermayer --- libavcodec/prosumer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c index 6e98677b556d0..2fd9880ee1911 100644 --- a/libavcodec/prosumer.c +++ b/libavcodec/prosumer.c @@ -57,7 +57,7 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui b = lut[2 * idx]; while (1) { - if (bytestream2_get_bytes_left_p(pb) <= 0) + if (bytestream2_get_bytes_left_p(pb) <= 0 || bytestream2_get_eof(pb)) return 0; if (((b & 0xFF00u) != 0x8000u) || (b & 0xFFu)) { if ((b & 0xFF00u) != 0x8000u) { From a163384467ddaef143b86d611d3717ffbc4a0134 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Oct 2018 10:18:45 +0100 Subject: [PATCH 010/153] avcodec/prosumer: Remove unneeded () Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 506839a3e9cc34c8f719937430008fc12d132fce) Signed-off-by: Michael Niedermayer --- libavcodec/prosumer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c index 2fd9880ee1911..24905ac80faf3 100644 --- a/libavcodec/prosumer.c +++ b/libavcodec/prosumer.c @@ -59,7 +59,7 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui while (1) { if (bytestream2_get_bytes_left_p(pb) <= 0 || bytestream2_get_eof(pb)) return 0; - if (((b & 0xFF00u) != 0x8000u) || (b & 0xFFu)) { + if ((b & 0xFF00u) != 0x8000u || (b & 0xFFu)) { if ((b & 0xFF00u) != 0x8000u) { bytestream2_put_le16(pb, b); } else if (b & 0xFFu) { From fd05e20650a50f3cd2b660367d0e73cb8fef9a07 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Oct 2018 10:19:08 +0100 Subject: [PATCH 011/153] avcodec/prosumer: Remove always true check in decompress() Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 1dfa0b6f36d29293f2d0219c4095dc8bb7a4b0dc) Signed-off-by: Michael Niedermayer --- libavcodec/prosumer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c index 24905ac80faf3..3125636cf1c56 100644 --- a/libavcodec/prosumer.c +++ b/libavcodec/prosumer.c @@ -62,7 +62,7 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui if ((b & 0xFF00u) != 0x8000u || (b & 0xFFu)) { if ((b & 0xFF00u) != 0x8000u) { bytestream2_put_le16(pb, b); - } else if (b & 0xFFu) { + } else { idx = 0; for (int i = 0; i < (b & 0xFFu); i++) bytestream2_put_le32(pb, 0); From 2f04b78b95464c46468c1d8c252f2360ffe7c183 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 31 Oct 2018 10:19:43 +0100 Subject: [PATCH 012/153] avcodec/prosumer: Simplify bit juggling of the c variable in decompress() Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 66425add270cd262a22c0fdaf6aad09a0db6f8c0) Signed-off-by: Michael Niedermayer --- libavcodec/prosumer.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c index 3125636cf1c56..505de71980103 100644 --- a/libavcodec/prosumer.c +++ b/libavcodec/prosumer.c @@ -69,15 +69,13 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui } c = b >> 16; if (c & 0xFF00u) { - c = (((c >> 8) & 0xFFu) | (c & 0xFF00)) & 0xF00F; fill = lut[2 * idx + 1]; - if ((c & 0xFF00u) == 0x1000) { + if ((c & 0xF000u) == 0x1000) { bytestream2_put_le16(pb, fill); - c &= 0xFFFF00FFu; } else { bytestream2_put_le32(pb, fill); - c &= 0xFFFF00FFu; } + c = (c >> 8) & 0x0Fu; } while (c) { a <<= 4; From 7d23ccac8d371e7ea28960d23a812f6b8446a642 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 28 Oct 2018 21:08:39 +0100 Subject: [PATCH 013/153] avcodec/mpegaudio_parser: Consume more than 0 bytes in case of the unsupported mp3adu case Fixes: Timeout Fixes: 10966/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MP3ADU_fuzzer-5348695024336896 Fixes: 10969/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MP3ADUFLOAT_fuzzer-5691669402877952 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit df91af140c5543cfbbed187f696e79b554d2c135) Signed-off-by: Michael Niedermayer --- libavcodec/mpegaudio_parser.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mpegaudio_parser.c b/libavcodec/mpegaudio_parser.c index a109f12701b14..1005e89aaeabd 100644 --- a/libavcodec/mpegaudio_parser.c +++ b/libavcodec/mpegaudio_parser.c @@ -101,7 +101,7 @@ static int mpegaudio_parse(AVCodecParserContext *s1, "MP3ADU full parser"); *poutbuf = NULL; *poutbuf_size = 0; - return 0; /* parsers must not return error codes */ + return buf_size; /* parsers must not return error codes */ } break; From bc5777bdab7d5515088713f73507d3a49df7695d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 4 Nov 2018 19:02:55 +0100 Subject: [PATCH 014/153] avcodec/mpeg4videodec: Clear partitioned frame in decode_studio_vop_header() partitioned_frame is also set/cleared in decode_vop_header() Fixes: out of array read Fixes: 9789/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEG4_fuzzer-5638681627983872 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 074187d599a2ece2bdf77bd08b4b797c5800eda6) Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4videodec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index 233b8525ceabd..f44ee76bd4194 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3056,6 +3056,7 @@ static int decode_studio_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) if (get_bits_left(gb) <= 32) return 0; + s->partitioned_frame = 0; s->decode_mb = mpeg4_decode_studio_mb; decode_smpte_tc(ctx, gb); From 7ebc27e1fa73c4db3409166b3465825a613bfa86 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 4 Nov 2018 20:00:16 +0100 Subject: [PATCH 015/153] avcodec/cavsdec: Propagate error codes inside decode_mb_i() Fixes: Timeout Fixes: 10702/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CAVS_fuzzer-5669940938407936 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit c1cee0565692c541f589aefd7f375d37f55b9d94) Signed-off-by: Michael Niedermayer --- libavcodec/cavsdec.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/libavcodec/cavsdec.c b/libavcodec/cavsdec.c index c7fff67c06c66..5f3b354518e64 100644 --- a/libavcodec/cavsdec.c +++ b/libavcodec/cavsdec.c @@ -591,14 +591,21 @@ static int decode_residual_block(AVSContext *h, GetBitContext *gb, } -static inline void decode_residual_chroma(AVSContext *h) +static inline int decode_residual_chroma(AVSContext *h) { - if (h->cbp & (1 << 4)) - decode_residual_block(h, &h->gb, chroma_dec, 0, + if (h->cbp & (1 << 4)) { + int ret = decode_residual_block(h, &h->gb, chroma_dec, 0, ff_cavs_chroma_qp[h->qp], h->cu, h->c_stride); - if (h->cbp & (1 << 5)) - decode_residual_block(h, &h->gb, chroma_dec, 0, + if (ret < 0) + return ret; + } + if (h->cbp & (1 << 5)) { + int ret = decode_residual_block(h, &h->gb, chroma_dec, 0, ff_cavs_chroma_qp[h->qp], h->cv, h->c_stride); + if (ret < 0) + return ret; + } + return 0; } static inline int decode_residual_inter(AVSContext *h) @@ -649,6 +656,7 @@ static int decode_mb_i(AVSContext *h, int cbp_code) uint8_t top[18]; uint8_t *left = NULL; uint8_t *d; + int ret; ff_cavs_init_mb(h); @@ -692,8 +700,11 @@ static int decode_mb_i(AVSContext *h, int cbp_code) ff_cavs_load_intra_pred_luma(h, top, &left, block); h->intra_pred_l[h->pred_mode_Y[scan3x3[block]]] (d, top, left, h->l_stride); - if (h->cbp & (1<qp, d, h->l_stride); + if (h->cbp & (1<qp, d, h->l_stride); + if (ret < 0) + return ret; + } } /* chroma intra prediction */ @@ -703,7 +714,9 @@ static int decode_mb_i(AVSContext *h, int cbp_code) h->intra_pred_c[pred_mode_uv](h->cv, &h->top_border_v[h->mbx * 10], h->left_border_v, h->c_stride); - decode_residual_chroma(h); + ret = decode_residual_chroma(h); + if (ret < 0) + return ret; ff_cavs_filter(h, I_8X8); set_mv_intra(h); return 0; From 63c1e291ef7ba97ce0dc7c0bdd46b81f71a52b9d Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Thu, 1 Nov 2018 21:03:59 +0100 Subject: [PATCH 016/153] avformat/ftp: allow nonstandard 202 reply to OPTS UTF8 Fixes ticket #7481. Signed-off-by: Marton Balint (cherry picked from commit 8e5a2495a8dad262e0a00fbca09b7779b4ebf0bf) --- libavformat/ftp.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavformat/ftp.c b/libavformat/ftp.c index 5063b7c204a3c..e0720674808dd 100644 --- a/libavformat/ftp.c +++ b/libavformat/ftp.c @@ -513,7 +513,7 @@ static int ftp_features(FTPContext *s) static const char *feat_command = "FEAT\r\n"; static const char *enable_utf8_command = "OPTS UTF8 ON\r\n"; static const int feat_codes[] = {211, 0}; - static const int opts_codes[] = {200, 451, 0}; + static const int opts_codes[] = {200, 202, 451, 0}; av_freep(&s->features); if (ftp_send_command(s, feat_command, feat_codes, &s->features) != 211) { @@ -521,7 +521,8 @@ static int ftp_features(FTPContext *s) } if (ftp_has_feature(s, "UTF8")) { - if (ftp_send_command(s, enable_utf8_command, opts_codes, NULL) == 200) + int ret = ftp_send_command(s, enable_utf8_command, opts_codes, NULL); + if (ret == 200 || ret == 202) s->utf8 = 1; } From 1c98cf4ddd38400793a4d01b3c3a662beb9e3ba8 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 2 Oct 2018 21:08:54 -0300 Subject: [PATCH 017/153] avformat/ivfenc: use the av1_metadata bsf to insert Temporal Delimiter OBUs if needed Reviewed-by: Mark Thompson Signed-off-by: James Almer (cherry picked from commit 2d2af23349cae0d84c8ed51c249bfc1e6f2e28a2) --- configure | 1 + libavformat/ivfenc.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/configure b/configure index 5a5d0b0868fdf..f3fa0cde861f2 100755 --- a/configure +++ b/configure @@ -3180,6 +3180,7 @@ image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" +ivf_muxer_select="av1_metadata" matroska_audio_muxer_select="matroska_muxer" matroska_demuxer_select="iso_media riffdec" matroska_demuxer_suggest="bzlib lzo zlib" diff --git a/libavformat/ivfenc.c b/libavformat/ivfenc.c index 66441a2a43304..adf72117e9343 100644 --- a/libavformat/ivfenc.c +++ b/libavformat/ivfenc.c @@ -97,6 +97,8 @@ static int ivf_check_bitstream(struct AVFormatContext *s, const AVPacket *pkt) if (st->codecpar->codec_id == AV_CODEC_ID_VP9) ret = ff_stream_add_bitstream_filter(st, "vp9_superframe", NULL); + else if (st->codecpar->codec_id == AV_CODEC_ID_AV1) + ret = ff_stream_add_bitstream_filter(st, "av1_metadata", "td=insert"); return ret; } From acd13f12556bd1e8d90a0afe1cbd3a949adf26a2 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 5 Nov 2018 00:01:54 +0000 Subject: [PATCH 018/153] configure: Fix av1_metadata BSF dependency (cherry picked from commit 34429182b93123a25e38819ef15bdae42793209f) --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index f3fa0cde861f2..23ad59031c23f 100755 --- a/configure +++ b/configure @@ -3180,7 +3180,7 @@ image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" -ivf_muxer_select="av1_metadata" +ivf_muxer_select="av1_metadata_bsf" matroska_audio_muxer_select="matroska_muxer" matroska_demuxer_select="iso_media riffdec" matroska_demuxer_suggest="bzlib lzo zlib" From 398a70309e4fa99433e98ab7f184ee7eb0abbca4 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 4 Nov 2018 17:07:39 -0300 Subject: [PATCH 019/153] avcodec/cbs_av1: fix decoder/encoder_buffer_delay variable types buffer_delay_length_minus_1 is five bits long, meaning decode_buffer_delay and encoder_buffer_delay can have values up to 32 bits long. Reviewed-by: Mark Thompson Signed-off-by: James Almer (cherry picked from commit 89a0d33e3a53e8edefd734b131a7035d13052947) --- libavcodec/cbs_av1.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h index b66a09c3896f8..614a0bf1088ab 100644 --- a/libavcodec/cbs_av1.h +++ b/libavcodec/cbs_av1.h @@ -87,8 +87,8 @@ typedef struct AV1RawSequenceHeader { uint8_t seq_level_idx[AV1_MAX_OPERATING_POINTS]; uint8_t seq_tier[AV1_MAX_OPERATING_POINTS]; uint8_t decoder_model_present_for_this_op[AV1_MAX_OPERATING_POINTS]; - uint8_t decoder_buffer_delay[AV1_MAX_OPERATING_POINTS]; - uint8_t encoder_buffer_delay[AV1_MAX_OPERATING_POINTS]; + uint32_t decoder_buffer_delay[AV1_MAX_OPERATING_POINTS]; + uint32_t encoder_buffer_delay[AV1_MAX_OPERATING_POINTS]; uint8_t low_delay_mode_flag[AV1_MAX_OPERATING_POINTS]; uint8_t initial_display_delay_present_for_this_op[AV1_MAX_OPERATING_POINTS]; uint8_t initial_display_delay_minus_1[AV1_MAX_OPERATING_POINTS]; From 066ff02621cea7d78d7791c91e0d916c30bffb27 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 5 Nov 2018 14:22:05 +0000 Subject: [PATCH 020/153] configure: Add missing IVF muxer BSF dependency (cherry picked from commit a4fb2b115071220f23ad7b3d82037647e94279ed) --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index 23ad59031c23f..5e8c20f8fb6f5 100755 --- a/configure +++ b/configure @@ -3180,7 +3180,7 @@ image2_alias_pix_demuxer_select="image2_demuxer" image2_brender_pix_demuxer_select="image2_demuxer" ipod_muxer_select="mov_muxer" ismv_muxer_select="mov_muxer" -ivf_muxer_select="av1_metadata_bsf" +ivf_muxer_select="av1_metadata_bsf vp9_superframe_bsf" matroska_audio_muxer_select="matroska_muxer" matroska_demuxer_select="iso_media riffdec" matroska_demuxer_suggest="bzlib lzo zlib" From ec1b5216fc65602b97cf5dc97a9a9a266f38894f Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Mon, 5 Nov 2018 14:22:10 +0000 Subject: [PATCH 021/153] configure: Add missing V4L2 M2M decoder BSF dependencies (cherry picked from commit e9d2e3fdaacb6872dd689ffd5a65e476b70dee3d) --- configure | 2 ++ 1 file changed, 2 insertions(+) diff --git a/configure b/configure index 5e8c20f8fb6f5..e79dae896c849 100755 --- a/configure +++ b/configure @@ -2957,6 +2957,7 @@ h264_rkmpp_decoder_deps="rkmpp" h264_rkmpp_decoder_select="h264_mp4toannexb_bsf" h264_vaapi_encoder_select="cbs_h264 vaapi_encode" h264_v4l2m2m_decoder_deps="v4l2_m2m h264_v4l2_m2m" +h264_v4l2m2m_decoder_select="h264_mp4toannexb_bsf" h264_v4l2m2m_encoder_deps="v4l2_m2m h264_v4l2_m2m" hevc_amf_encoder_deps="amf" hevc_cuvid_decoder_deps="cuvid" @@ -2971,6 +2972,7 @@ hevc_rkmpp_decoder_select="hevc_mp4toannexb_bsf" hevc_vaapi_encoder_deps="VAEncPictureParameterBufferHEVC" hevc_vaapi_encoder_select="cbs_h265 vaapi_encode" hevc_v4l2m2m_decoder_deps="v4l2_m2m hevc_v4l2_m2m" +hevc_v4l2m2m_decoder_select="hevc_mp4toannexb_bsf" hevc_v4l2m2m_encoder_deps="v4l2_m2m hevc_v4l2_m2m" mjpeg_cuvid_decoder_deps="cuvid" mjpeg_qsv_encoder_deps="libmfx" From af3fccfeff74da54fc3e702fbb6757c2aad2814e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 4 Nov 2018 23:56:39 +0000 Subject: [PATCH 022/153] cbs_av1: Fix header writing when already aligned (cherry picked from commit 6bdb7712ae0267ba4f69c7434d2b3dee12762d1d) --- libavcodec/cbs_av1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index 9bac9dde0912a..1c49d90f51023 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -1179,7 +1179,7 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, if (err < 0) return err; end_pos = put_bits_count(pbc); - obu->obu_size = (end_pos - start_pos + 7) / 8; + obu->obu_size = header_size = (end_pos - start_pos + 7) / 8; } else { // Empty OBU. obu->obu_size = 0; From 10506de9ad1fb050737ef79cf4853742b793c37d Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 4 Nov 2018 23:58:01 +0000 Subject: [PATCH 023/153] cbs_av1: Support redundant frame headers (cherry picked from commit f5894178fb8063ec17c61c04df96a70607ca2daa) --- libavcodec/cbs_av1.c | 16 ++++-- libavcodec/cbs_av1.h | 5 +- libavcodec/cbs_av1_syntax_template.c | 82 +++++++++++++++++++++++++--- 3 files changed, 91 insertions(+), 12 deletions(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index 1c49d90f51023..ff32a6fca595b 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -996,7 +996,10 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, case AV1_OBU_REDUNDANT_FRAME_HEADER: { err = cbs_av1_read_frame_header_obu(ctx, &gbc, - &obu->obu.frame_header); + &obu->obu.frame_header, + obu->header.obu_type == + AV1_OBU_REDUNDANT_FRAME_HEADER, + unit->data_ref); if (err < 0) return err; } @@ -1016,7 +1019,8 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, break; case AV1_OBU_FRAME: { - err = cbs_av1_read_frame_obu(ctx, &gbc, &obu->obu.frame); + err = cbs_av1_read_frame_obu(ctx, &gbc, &obu->obu.frame, + unit->data_ref); if (err < 0) return err; @@ -1124,7 +1128,10 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, case AV1_OBU_REDUNDANT_FRAME_HEADER: { err = cbs_av1_write_frame_header_obu(ctx, pbc, - &obu->obu.frame_header); + &obu->obu.frame_header, + obu->header.obu_type == + AV1_OBU_REDUNDANT_FRAME_HEADER, + NULL); if (err < 0) return err; } @@ -1141,7 +1148,7 @@ static int cbs_av1_write_obu(CodedBitstreamContext *ctx, break; case AV1_OBU_FRAME: { - err = cbs_av1_write_frame_obu(ctx, pbc, &obu->obu.frame); + err = cbs_av1_write_frame_obu(ctx, pbc, &obu->obu.frame, NULL); if (err < 0) return err; @@ -1302,6 +1309,7 @@ static void cbs_av1_close(CodedBitstreamContext *ctx) CodedBitstreamAV1Context *priv = ctx->priv_data; av_buffer_unref(&priv->sequence_header_ref); + av_buffer_unref(&priv->frame_header_ref); av_freep(&priv->write_buffer); } diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h index 614a0bf1088ab..f662265f755f0 100644 --- a/libavcodec/cbs_av1.h +++ b/libavcodec/cbs_av1.h @@ -399,7 +399,10 @@ typedef struct CodedBitstreamAV1Context { AV1RawSequenceHeader *sequence_header; AVBufferRef *sequence_header_ref; - int seen_frame_header; + int seen_frame_header; + AVBufferRef *frame_header_ref; + uint8_t *frame_header; + size_t frame_header_size; int temporal_id; int spatial_id; diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index e146bbf8bb62d..0da79b615d8c8 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -1463,24 +1463,90 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, } static int FUNC(frame_header_obu)(CodedBitstreamContext *ctx, RWContext *rw, - AV1RawFrameHeader *current) + AV1RawFrameHeader *current, int redundant, + AVBufferRef *rw_buffer_ref) { CodedBitstreamAV1Context *priv = ctx->priv_data; - int err; - - HEADER("Frame Header"); + int start_pos, fh_bits, fh_bytes, err; + uint8_t *fh_start; if (priv->seen_frame_header) { - // Nothing to do. + if (!redundant) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid repeated " + "frame header OBU.\n"); + return AVERROR_INVALIDDATA; + } else { + GetBitContext fh; + size_t i, b; + uint32_t val; + + HEADER("Redundant Frame Header"); + + av_assert0(priv->frame_header_ref && priv->frame_header); + + init_get_bits(&fh, priv->frame_header, + priv->frame_header_size); + for (i = 0; i < priv->frame_header_size; i += 8) { + b = FFMIN(priv->frame_header_size - i, 8); + val = get_bits(&fh, b); + xf(b, frame_header_copy[i], + val, val, val, 1, i / 8); + } + } } else { + if (redundant) + HEADER("Redundant Frame Header (used as Frame Header)"); + else + HEADER("Frame Header"); + priv->seen_frame_header = 1; +#ifdef READ + start_pos = get_bits_count(rw); +#else + start_pos = put_bits_count(rw); +#endif + CHECK(FUNC(uncompressed_header)(ctx, rw, current)); if (current->show_existing_frame) { priv->seen_frame_header = 0; } else { priv->seen_frame_header = 1; + + av_buffer_unref(&priv->frame_header_ref); + +#ifdef READ + fh_bits = get_bits_count(rw) - start_pos; + fh_start = (uint8_t*)rw->buffer + start_pos / 8; +#else + // Need to flush the bitwriter so that we can copy its output, + // but use a copy so we don't affect the caller's structure. + { + PutBitContext tmp = *rw; + flush_put_bits(&tmp); + } + + fh_bits = put_bits_count(rw) - start_pos; + fh_start = rw->buf + start_pos / 8; +#endif + fh_bytes = (fh_bits + 7) / 8; + + priv->frame_header_size = fh_bits; + + if (rw_buffer_ref) { + priv->frame_header_ref = av_buffer_ref(rw_buffer_ref); + if (!priv->frame_header_ref) + return AVERROR(ENOMEM); + priv->frame_header = fh_start; + } else { + priv->frame_header_ref = + av_buffer_alloc(fh_bytes + AV_INPUT_BUFFER_PADDING_SIZE); + if (!priv->frame_header_ref) + return AVERROR(ENOMEM); + priv->frame_header = priv->frame_header_ref->data; + memcpy(priv->frame_header, fh_start, fh_bytes); + } } } @@ -1524,11 +1590,13 @@ static int FUNC(tile_group_obu)(CodedBitstreamContext *ctx, RWContext *rw, } static int FUNC(frame_obu)(CodedBitstreamContext *ctx, RWContext *rw, - AV1RawFrame *current) + AV1RawFrame *current, + AVBufferRef *rw_buffer_ref) { int err; - CHECK(FUNC(frame_header_obu)(ctx, rw, ¤t->header)); + CHECK(FUNC(frame_header_obu)(ctx, rw, ¤t->header, + 0, rw_buffer_ref)); CHECK(FUNC(byte_alignment)(ctx, rw)); From 11dff170ef79d26d1de2bcd13b603a6c4c5c9815 Mon Sep 17 00:00:00 2001 From: Mark Wu Date: Tue, 23 Oct 2018 12:49:08 +0800 Subject: [PATCH 024/153] avcodec/hevcdec: fix non-ref frame judgement After inspecting the source code of x265, mpv and ffmpeg, I've found that ffmpeg mistakenly regards EVC_NAL_BLA_N_LP and HEVC_NAL_IDR_N_LP as non- reference frames, which are acutally reference frames according to the specification in x265, and drops them. This patch should address the problem. I have tested it with mpv. Signed-off-by: Mark Wu Signed-off-by: James Almer (cherry picked from commit 10bc4c3a7df7bb26303067b97311b7eeedfd453e) --- libavcodec/hevcdec.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/libavcodec/hevcdec.h b/libavcodec/hevcdec.h index f0f588f2b826a..dd951aae065a0 100644 --- a/libavcodec/hevcdec.h +++ b/libavcodec/hevcdec.h @@ -559,8 +559,6 @@ static av_always_inline int ff_hevc_nal_is_nonref(enum HEVCNALUnitType type) case HEVC_NAL_VCL_N10: case HEVC_NAL_VCL_N12: case HEVC_NAL_VCL_N14: - case HEVC_NAL_BLA_N_LP: - case HEVC_NAL_IDR_N_LP: return 1; break; default: break; From 4f1e07090a9f6064078cac694f1d7148f86176c3 Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Wed, 14 Nov 2018 22:56:18 +0000 Subject: [PATCH 025/153] configure: Add missing xlib dependency for VAAPI X11 code Fixes #7538. (cherry picked from commit 2ce3a48f30fe3cec7153aa3f18a1012a366aca3a) --- configure | 1 + 1 file changed, 1 insertion(+) diff --git a/configure b/configure index e79dae896c849..a70c5f9e9e397 100755 --- a/configure +++ b/configure @@ -2812,6 +2812,7 @@ d3d11va_deps="dxva_h ID3D11VideoDecoder ID3D11VideoContext" dxva2_deps="dxva2api_h DXVA2_ConfigPictureDecode ole32 user32" ffnvcodec_deps_any="libdl LoadLibrary" nvdec_deps="ffnvcodec" +vaapi_x11_deps="xlib" videotoolbox_hwaccel_deps="videotoolbox pthreads" videotoolbox_hwaccel_extralibs="-framework QuartzCore" xvmc_deps="X11_extensions_XvMClib_h" From 49bc641e89f7c89648f28feafa2daa3756ba9c7d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 10 Nov 2018 22:51:18 -0300 Subject: [PATCH 026/153] avcodec/cbs_av1: fix storage size for segmentation_params feature_value fields The valid range is -255 to 255. Reviewed-by: Mark Thompson Signed-off-by: James Almer (cherry picked from commit 79831f4531d98c3c1eab96c10f1135d08abef5f3) --- libavcodec/cbs_av1.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h index f662265f755f0..84622ed189dc0 100644 --- a/libavcodec/cbs_av1.h +++ b/libavcodec/cbs_av1.h @@ -210,7 +210,7 @@ typedef struct AV1RawFrameHeader { uint8_t segmentation_temporal_update; uint8_t segmentation_update_data; uint8_t feature_enabled[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; - uint8_t feature_value[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; + int16_t feature_value[AV1_MAX_SEGMENTS][AV1_SEG_LVL_MAX]; uint8_t delta_q_present; uint8_t delta_q_res; From a9e9303f26597b2a166374cd46b00adc0401e634 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sat, 10 Nov 2018 22:52:12 -0300 Subject: [PATCH 027/153] avcodec/cbs_av1: fix parsing signed integer values Reviewed-by: Mark Thompson Signed-off-by: James Almer (cherry picked from commit f0f2832a5ce93bad9b1d29f99df6bda2380fc41c) --- libavcodec/cbs_av1.c | 30 +++++++++--------------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index ff32a6fca595b..ed5211be1924a 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -189,30 +189,26 @@ static int cbs_av1_read_su(CodedBitstreamContext *ctx, GetBitContext *gbc, int width, const char *name, const int *subscripts, int32_t *write_to) { - uint32_t magnitude; - int position, sign; + int position; int32_t value; if (ctx->trace_enable) position = get_bits_count(gbc); - if (get_bits_left(gbc) < width + 1) { + if (get_bits_left(gbc) < width) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid signed value at " "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA; } - magnitude = get_bits(gbc, width); - sign = get_bits1(gbc); - value = sign ? -(int32_t)magnitude : magnitude; + value = get_sbits(gbc, width); if (ctx->trace_enable) { char bits[33]; int i; for (i = 0; i < width; i++) - bits[i] = magnitude >> (width - i - 1) & 1 ? '1' : '0'; - bits[i] = sign ? '1' : '0'; - bits[i + 1] = 0; + bits[i] = value & (1 << (width - i - 1)) ? '1' : '0'; + bits[i] = 0; ff_cbs_trace_syntax_element(ctx, position, name, subscripts, bits, value); @@ -226,29 +222,21 @@ static int cbs_av1_write_su(CodedBitstreamContext *ctx, PutBitContext *pbc, int width, const char *name, const int *subscripts, int32_t value) { - uint32_t magnitude; - int sign; - - if (put_bits_left(pbc) < width + 1) + if (put_bits_left(pbc) < width) return AVERROR(ENOSPC); - sign = value < 0; - magnitude = sign ? -value : value; - if (ctx->trace_enable) { char bits[33]; int i; for (i = 0; i < width; i++) - bits[i] = magnitude >> (width - i - 1) & 1 ? '1' : '0'; - bits[i] = sign ? '1' : '0'; - bits[i + 1] = 0; + bits[i] = value & (1 << (width - i - 1)) ? '1' : '0'; + bits[i] = 0; ff_cbs_trace_syntax_element(ctx, put_bits_count(pbc), name, subscripts, bits, value); } - put_bits(pbc, width, magnitude); - put_bits(pbc, 1, sign); + put_sbits(pbc, width, value); return 0; } From fed94c2f22fc165e1b012e3b621802b4d03e9214 Mon Sep 17 00:00:00 2001 From: Mark Harris Date: Sun, 11 Nov 2018 22:54:04 -0800 Subject: [PATCH 028/153] avfilter/vf_fade: fix start/duration max value A fade out (usually at the end of a video) can easily start beyond INT32_MAX (about 36 minutes). Regression since d40dc64173. (cherry picked from commit ae4323548ae821db81b73bc66cf5a2f9885296cb) --- libavfilter/vf_fade.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c index c30c41db0da4a..17eca109b6ccb 100644 --- a/libavfilter/vf_fade.c +++ b/libavfilter/vf_fade.c @@ -386,13 +386,13 @@ static const AVOption fade_options[] = { OFFSET(nb_frames), AV_OPT_TYPE_INT, { .i64 = 25 }, 0, INT_MAX, FLAGS }, { "alpha", "fade alpha if it is available on the input", OFFSET(alpha), AV_OPT_TYPE_BOOL, {.i64 = 0 }, 0, 1, FLAGS }, { "start_time", "Number of seconds of the beginning of the effect.", - OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS }, + OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, { "st", "Number of seconds of the beginning of the effect.", - OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS }, + OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, { "duration", "Duration of the effect in seconds.", - OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS }, + OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, { "d", "Duration of the effect in seconds.", - OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS }, + OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, { "color", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS }, { "c", "set color", OFFSET(color_rgba), AV_OPT_TYPE_COLOR, {.str = "black"}, CHAR_MIN, CHAR_MAX, FLAGS }, { NULL } From bb01cd3cc01c9982e4b57f8ce5cfd6ec4724f848 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Mon, 12 Nov 2018 22:00:49 +0100 Subject: [PATCH 029/153] avfilter/af_afade: fix duration maximum Signed-off-by: Marton Balint (cherry picked from commit aecd63b926812148014c4f01270473722ae5e945) --- libavfilter/af_afade.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/af_afade.c b/libavfilter/af_afade.c index 9aab644039cdc..8d9ba916bf998 100644 --- a/libavfilter/af_afade.c +++ b/libavfilter/af_afade.c @@ -245,8 +245,8 @@ static const AVOption afade_options[] = { { "ns", "set number of samples for fade duration", OFFSET(nb_samples), AV_OPT_TYPE_INT64, {.i64 = 44100}, 1, INT64_MAX, FLAGS }, { "start_time", "set time to start fading", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, { "st", "set time to start fading", OFFSET(start_time), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, - { "duration", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS }, - { "d", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT32_MAX, FLAGS }, + { "duration", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, + { "d", "set fade duration", OFFSET(duration), AV_OPT_TYPE_DURATION, {.i64 = 0. }, 0, INT64_MAX, FLAGS }, { "curve", "set fade curve type", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, 0, NB_CURVES - 1, FLAGS, "curve" }, { "c", "set fade curve type", OFFSET(curve), AV_OPT_TYPE_INT, {.i64 = TRI }, 0, NB_CURVES - 1, FLAGS, "curve" }, { "tri", "linear slope", 0, AV_OPT_TYPE_CONST, {.i64 = TRI }, 0, 0, FLAGS, "curve" }, From d4c5f515f09076635bf5e1591e5ff9d21ac13572 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sat, 17 Nov 2018 23:26:24 +0100 Subject: [PATCH 030/153] avcodec/mpeg_er: fix clearing chroma blocks for 422 and 444 Fixes ticket #7494. Signed-off-by: Marton Balint (cherry picked from commit e3a96309826dd0ea33db0300f7c75414fdbea0a4) --- libavcodec/mpeg_er.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/mpeg_er.c b/libavcodec/mpeg_er.c index ada1a1692f339..f54cb8548ba07 100644 --- a/libavcodec/mpeg_er.c +++ b/libavcodec/mpeg_er.c @@ -78,6 +78,8 @@ static void mpeg_er_decode_mb(void *opaque, int ref, int mv_dir, int mv_type, ff_update_block_index(s); s->bdsp.clear_blocks(s->block[0]); + if (!s->chroma_y_shift) + s->bdsp.clear_blocks(s->block[6]); s->dest[0] = s->current_picture.f->data[0] + s->mb_y * 16 * s->linesize + From 9efc591cb72b96a5880b0968978692fa4c1d99b6 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Tue, 20 Nov 2018 23:18:47 +0100 Subject: [PATCH 031/153] avfilter/vf_overlay: fix crash with negative y (cherry picked from commit 57815cfad5c5d6beb6f3fc0ae86b050a970d3a08) --- libavfilter/vf_overlay.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index ba25893739fc4..a12e7a793f0ca 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -473,12 +473,12 @@ static av_always_inline void blend_plane(AVFilterContext *ctx, slice_start = (jmax * jobnr) / nb_jobs; slice_end = (jmax * (jobnr+1)) / nb_jobs; - sp = src->data[i] + slice_start * src->linesize[i]; + sp = src->data[i] + (j + slice_start) * src->linesize[i]; dp = dst->data[dst_plane] - + (yp + slice_start) * dst->linesize[dst_plane] + + (yp + j + slice_start) * dst->linesize[dst_plane] + dst_offset; - ap = src->data[3] + (slice_start << vsub) * src->linesize[3]; - dap = dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3]; + ap = src->data[3] + (j + slice_start << vsub) * src->linesize[3]; + dap = dst->data[3] + ((yp + j + slice_start) << vsub) * dst->linesize[3]; for (j = j + slice_start; j < slice_end; j++) { k = FFMAX(-xp, 0); From fcffed470a5236bc1799bc3022d588704d9ae5ef Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Wed, 21 Nov 2018 11:45:02 +0100 Subject: [PATCH 032/153] avformat/movenc: fix size calculation in mov_write_eac3_tag() Otherwise it would assert when flushing bits. (cherry picked from commit 027f032bbce9bdf7bbec40665b98590cade33416) --- libavformat/movenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 33978ee1b0249..bee8e89760adc 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -541,7 +541,7 @@ static int mov_write_eac3_tag(AVIOContext *pb, MOVTrack *track) return AVERROR(EINVAL); info = track->eac3_priv; - size = 2 + 4 * (info->num_ind_sub + 1); + size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3); buf = av_malloc(size); if (!buf) { size = AVERROR(ENOMEM); From 59e30c05d74e59d28f2ec4ffd4dbf1822f921f06 Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Thu, 22 Nov 2018 21:28:59 +0100 Subject: [PATCH 033/153] avformat/movenc: get number of written bytes from bitstream writer Update fate test. (cherry picked from commit 97d1ee437bbf67d7e3897bc73df4f7d9771ac309) --- libavformat/movenc.c | 2 +- tests/ref/fate/copy-trac3074 | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index bee8e89760adc..6dab5193b044e 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -563,12 +563,12 @@ static int mov_write_eac3_tag(AVIOContext *pb, MOVTrack *track) put_bits(&pbc, 4, info->substream[i].num_dep_sub); if (!info->substream[i].num_dep_sub) { put_bits(&pbc, 1, 0); /* reserved */ - size--; } else { put_bits(&pbc, 9, info->substream[i].chan_loc); } } flush_put_bits(&pbc); + size = put_bits_count(&pbc) >> 3; avio_wb32(pb, size + 8); ffio_wfourcc(pb, "dec3"); diff --git a/tests/ref/fate/copy-trac3074 b/tests/ref/fate/copy-trac3074 index 5ce56942604a1..ff66900253f88 100644 --- a/tests/ref/fate/copy-trac3074 +++ b/tests/ref/fate/copy-trac3074 @@ -1,5 +1,5 @@ -39aef1afff761d673fd1be07182941d1 *tests/data/fate/copy-trac3074.mp4 -333991 tests/data/fate/copy-trac3074.mp4 +f92a201033712bda262f1e071e25544a *tests/data/fate/copy-trac3074.mp4 +333992 tests/data/fate/copy-trac3074.mp4 #tb 0: 1/48000 #media_type 0: audio #codec_id 0: eac3 From a4ddc3c9fc60e6cf8123966f4ca7a7db70aa58eb Mon Sep 17 00:00:00 2001 From: Paul B Mahol Date: Mon, 3 Dec 2018 10:00:01 +0100 Subject: [PATCH 034/153] avfilter/vf_overlay: fix filtering with negative y (cherry picked from commit 8440835dbe93ef9972ceb940af9bda9bc0e178e7) --- libavfilter/vf_overlay.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c index a12e7a793f0ca..0a8f089c0d57d 100644 --- a/libavfilter/vf_overlay.c +++ b/libavfilter/vf_overlay.c @@ -380,15 +380,15 @@ static av_always_inline void blend_slice_packed_rgb(AVFilterContext *ctx, uint8_t *S, *sp, *d, *dp; i = FFMAX(-y, 0); - imax = FFMIN(-y + dst_h, src_h); + imax = FFMIN3(-y + dst_h, FFMIN(src_h, dst_h), y + src_h); - slice_start = (imax * jobnr) / nb_jobs; - slice_end = (imax * (jobnr+1)) / nb_jobs; + slice_start = i + (imax * jobnr) / nb_jobs; + slice_end = i + (imax * (jobnr+1)) / nb_jobs; - sp = src->data[0] + (i + slice_start) * src->linesize[0]; - dp = dst->data[0] + (y + i + slice_start) * dst->linesize[0]; + sp = src->data[0] + (slice_start) * src->linesize[0]; + dp = dst->data[0] + (y + slice_start) * dst->linesize[0]; - for (i = i + slice_start; i < slice_end; i++) { + for (i = slice_start; i < slice_end; i++) { j = FFMAX(-x, 0); S = sp + j * sstep; d = dp + (x+j) * dstep; @@ -468,19 +468,19 @@ static av_always_inline void blend_plane(AVFilterContext *ctx, int slice_start, slice_end; j = FFMAX(-yp, 0); - jmax = FFMIN(-yp + dst_hp, src_hp); + jmax = FFMIN3(-yp + dst_hp, FFMIN(src_hp, dst_hp), yp + src_hp); - slice_start = (jmax * jobnr) / nb_jobs; - slice_end = (jmax * (jobnr+1)) / nb_jobs; + slice_start = j + (jmax * jobnr) / nb_jobs; + slice_end = j + (jmax * (jobnr+1)) / nb_jobs; - sp = src->data[i] + (j + slice_start) * src->linesize[i]; + sp = src->data[i] + (slice_start) * src->linesize[i]; dp = dst->data[dst_plane] - + (yp + j + slice_start) * dst->linesize[dst_plane] + + (yp + slice_start) * dst->linesize[dst_plane] + dst_offset; - ap = src->data[3] + (j + slice_start << vsub) * src->linesize[3]; - dap = dst->data[3] + ((yp + j + slice_start) << vsub) * dst->linesize[3]; + ap = src->data[3] + (slice_start << vsub) * src->linesize[3]; + dap = dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3]; - for (j = j + slice_start; j < slice_end; j++) { + for (j = slice_start; j < slice_end; j++) { k = FFMAX(-xp, 0); d = dp + (xp+k) * dst_step; s = sp + k; @@ -961,13 +961,13 @@ static int do_blend(FFFrameSync *fs) s->var_values[VAR_Y], s->y); } - if (s->x < mainpic->width && s->x + second->width >= 0 || + if (s->x < mainpic->width && s->x + second->width >= 0 && s->y < mainpic->height && s->y + second->height >= 0) { ThreadData td; td.dst = mainpic; td.src = second; - ctx->internal->execute(ctx, s->blend_slice, &td, NULL, FFMIN(FFMIN(mainpic->height - s->y, second->height), + ctx->internal->execute(ctx, s->blend_slice, &td, NULL, FFMIN(FFMAX(1, FFMIN3(s->y + second->height, FFMIN(second->height, mainpic->height), mainpic->height - s->y)), ff_filter_get_nb_threads(ctx))); } return ff_filter_frame(ctx->outputs[0], mainpic); From 5356e610010a25809e6e43146b813056a8929804 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 20 Dec 2018 12:26:43 -0300 Subject: [PATCH 035/153] avcodec/cbs_av1: fix parsing delta_frame_id_minus1 delta_frame_id_minus1 is not a single value in the bitstream, and can store values up to 17 bits wide. Fixes parsing files with frame ids. Reviewed-by: Mark Thompson Signed-off-by: James Almer (cherry picked from commit 064f9505f49816650516c7afe93e43d8f547891a) --- libavcodec/cbs_av1.h | 2 +- libavcodec/cbs_av1_syntax_template.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/cbs_av1.h b/libavcodec/cbs_av1.h index 84622ed189dc0..71ceff9427354 100644 --- a/libavcodec/cbs_av1.h +++ b/libavcodec/cbs_av1.h @@ -170,7 +170,7 @@ typedef struct AV1RawFrameHeader { uint8_t last_frame_idx; uint8_t golden_frame_idx; int8_t ref_frame_idx[AV1_REFS_PER_FRAME]; - uint8_t delta_frame_id_minus1; + uint32_t delta_frame_id_minus1[AV1_REFS_PER_FRAME]; uint8_t allow_high_precision_mv; uint8_t is_filter_switchable; diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index 0da79b615d8c8..48f4fab514a51 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -1323,8 +1323,8 @@ static int FUNC(uncompressed_header)(CodedBitstreamContext *ctx, RWContext *rw, if (!current->frame_refs_short_signaling) fbs(3, ref_frame_idx[i], 1, i); if (seq->frame_id_numbers_present_flag) { - fb(seq->delta_frame_id_length_minus_2 + 2, - delta_frame_id_minus1); + fbs(seq->delta_frame_id_length_minus_2 + 2, + delta_frame_id_minus1[i], 1, i); } } From b420f23566825192c3fc1f46fce24d19ffc1d72e Mon Sep 17 00:00:00 2001 From: Mark Thompson Date: Sun, 2 Dec 2018 20:49:24 +0000 Subject: [PATCH 036/153] cbs_av1: Fix reading of overlong uvlc codes The specification allows 2^32-1 to be encoded as any number of zeroes greater than 31, followed by a one. This previously failed because the trace code would overflow the array containing the string representation of the bits if there were more than 63 zeroes. Fix that by splitting the trace output into batches, and at the same time move it out of the default path. (While this seems likely to be a specification error, libaom does support it so we probably should as well.) From a test case by keval shah . Reviewed-by: Michael Niedermayer (cherry picked from commit b97a4b658814b2de8b9f2a3bce491c002d34de31) --- libavcodec/cbs_av1.c | 58 ++++++++++++++++++++++++++++++-------------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index ed5211be1924a..535139e7038f5 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -29,45 +29,67 @@ static int cbs_av1_read_uvlc(CodedBitstreamContext *ctx, GetBitContext *gbc, const char *name, uint32_t *write_to, uint32_t range_min, uint32_t range_max) { - uint32_t value; - int position, zeroes, i, j; - char bits[65]; + uint32_t zeroes, bits_value, value; + int position; if (ctx->trace_enable) position = get_bits_count(gbc); - zeroes = i = 0; + zeroes = 0; while (1) { - if (get_bits_left(gbc) < zeroes + 1) { + if (get_bits_left(gbc) < 1) { av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid uvlc code at " "%s: bitstream ended.\n", name); return AVERROR_INVALIDDATA; } - if (get_bits1(gbc)) { - bits[i++] = '1'; + if (get_bits1(gbc)) break; - } else { - bits[i++] = '0'; - ++zeroes; - } + ++zeroes; } if (zeroes >= 32) { value = MAX_UINT_BITS(32); } else { - value = get_bits_long(gbc, zeroes); - - for (j = 0; j < zeroes; j++) - bits[i++] = (value >> (zeroes - j - 1) & 1) ? '1' : '0'; + if (get_bits_left(gbc) < zeroes) { + av_log(ctx->log_ctx, AV_LOG_ERROR, "Invalid uvlc code at " + "%s: bitstream ended.\n", name); + return AVERROR_INVALIDDATA; + } - value += (1 << zeroes) - 1; + bits_value = get_bits_long(gbc, zeroes); + value = bits_value + (UINT32_C(1) << zeroes) - 1; } if (ctx->trace_enable) { + char bits[65]; + int i, j, k; + + if (zeroes >= 32) { + while (zeroes > 32) { + k = FFMIN(zeroes - 32, 32); + for (i = 0; i < k; i++) + bits[i] = '0'; + bits[i] = 0; + ff_cbs_trace_syntax_element(ctx, position, name, + NULL, bits, 0); + zeroes -= k; + position += k; + } + } + + for (i = 0; i < zeroes; i++) + bits[i] = '0'; + bits[i++] = '1'; + + if (zeroes < 32) { + for (j = 0; j < zeroes; j++) + bits[i++] = (bits_value >> (zeroes - j - 1) & 1) ? '1' : '0'; + } + bits[i] = 0; - ff_cbs_trace_syntax_element(ctx, position, name, NULL, - bits, value); + ff_cbs_trace_syntax_element(ctx, position, name, + NULL, bits, value); } if (value < range_min || value > range_max) { From ddc284300eb09b516cef96b6242041b410369302 Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Tue, 25 Dec 2018 22:26:18 +0100 Subject: [PATCH 037/153] avfilter/af_asetnsamples: fix last frame props Frame properties were not copied, so e.g. PTS was not set for the last frame. Regression since ef3babb2c70f564dc1634b3f29c6e35a2b2dc239. Signed-off-by: Marton Balint (cherry picked from commit f9e947845f9ac5ccb84cf5e6f4121ec2e23b9946) --- libavfilter/af_asetnsamples.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavfilter/af_asetnsamples.c b/libavfilter/af_asetnsamples.c index e8daec8d8f9a3..c60ce3063fa8c 100644 --- a/libavfilter/af_asetnsamples.c +++ b/libavfilter/af_asetnsamples.c @@ -76,6 +76,13 @@ static int activate(AVFilterContext *ctx) return AVERROR(ENOMEM); } + ret = av_frame_copy_props(pad_frame, frame); + if (ret < 0) { + av_frame_free(&pad_frame); + av_frame_free(&frame); + return ret; + } + av_samples_copy(pad_frame->extended_data, frame->extended_data, 0, 0, frame->nb_samples, frame->channels, frame->format); av_samples_set_silence(pad_frame->extended_data, frame->nb_samples, From ac50246cc49add4e53d6716afd454dbe86666efd Mon Sep 17 00:00:00 2001 From: Andreas Rheinhardt Date: Fri, 9 Nov 2018 06:31:38 +0100 Subject: [PATCH 038/153] h264_redundant_pps: Fix logging context The first element of H264RedundantPPSContext is not a pointer to an AVClass as required. Signed-off-by: Andreas Rheinhardt Signed-off-by: Michael Niedermayer (cherry picked from commit 6dafcb6fdb6271d35220b889833561705c2b366f) Signed-off-by: Michael Niedermayer --- libavcodec/h264_redundant_pps_bsf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_redundant_pps_bsf.c b/libavcodec/h264_redundant_pps_bsf.c index cc5a3060f5611..af247eef21953 100644 --- a/libavcodec/h264_redundant_pps_bsf.c +++ b/libavcodec/h264_redundant_pps_bsf.c @@ -91,7 +91,7 @@ static int h264_redundant_pps_filter(AVBSFContext *bsf, AVPacket *out) if (nal->type == H264_NAL_PPS) { h264_redundant_pps_fixup_pps(ctx, nal->content); if (!au_has_sps) { - av_log(ctx, AV_LOG_VERBOSE, "Deleting redundant PPS " + av_log(bsf, AV_LOG_VERBOSE, "Deleting redundant PPS " "at %"PRId64".\n", in->pts); ff_cbs_delete_unit(ctx->input, au, i); } From b66152a4e5e578c731f7e59e43f4db6b77d7c6d6 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 9 Nov 2018 23:07:23 +0100 Subject: [PATCH 039/153] avcodec/imm4: Use ff_set_dimensions() Fixes: Out of memory Fixes: 10970/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_IMM4_fuzzer-5698750043914240 Reviewed-by: Paul B Mahol Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit c305e134ce23b46a1164527ade3e1b7e2ecedf5f) Signed-off-by: Michael Niedermayer --- libavcodec/imm4.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libavcodec/imm4.c b/libavcodec/imm4.c index a4e9b5d4d2a4c..b72f0be28ef79 100644 --- a/libavcodec/imm4.c +++ b/libavcodec/imm4.c @@ -428,8 +428,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, av_log(avctx, AV_LOG_ERROR, "Frame size change is unsupported.\n"); return AVERROR_INVALIDDATA; } - avctx->width = width; - avctx->height = height; + ret = ff_set_dimensions(avctx, width, height); + if (ret < 0) + return ret; } s->changed_size = 1; From 98a9d868d19b67808b035d121b71e0edeb6269c4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 9 Nov 2018 19:59:27 +0100 Subject: [PATCH 040/153] avcodec/shorten: Fix integer overflow with offset Fixes: signed integer overflow: -1625810908 - 582229060 cannot be represented in type 'int' Fixes: 10977/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SHORTEN_fuzzer-5732602018267136 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 2f888771cd1ce8d68d4b18a1009650c1f260aaf2) Signed-off-by: Michael Niedermayer --- libavcodec/shorten.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/shorten.c b/libavcodec/shorten.c index 4b45e6d6dc73a..4134af74cfe6d 100644 --- a/libavcodec/shorten.c +++ b/libavcodec/shorten.c @@ -382,7 +382,7 @@ static int decode_subframe_lpc(ShortenContext *s, int command, int channel, /* subtract offset from previous samples to use in prediction */ if (command == FN_QLPC && coffset) for (i = -pred_order; i < 0; i++) - s->decoded[channel][i] -= coffset; + s->decoded[channel][i] -= (unsigned)coffset; /* decode residual and do LPC prediction */ init_sum = pred_order ? (command == FN_QLPC ? s->lpcqoffset : 0) : coffset; @@ -397,7 +397,7 @@ static int decode_subframe_lpc(ShortenContext *s, int command, int channel, /* add offset to current samples */ if (command == FN_QLPC && coffset) for (i = 0; i < s->blocksize; i++) - s->decoded[channel][i] += coffset; + s->decoded[channel][i] += (unsigned)coffset; return 0; } From e69bb0fb05550523a143efdfeffd51d4d2e813c4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 13 Nov 2018 20:29:40 +0100 Subject: [PATCH 041/153] fftools/ffmpeg: Repair reinit_filter feature Signed-off-by: Michael Niedermayer (cherry picked from commit 35040048793bc5d19942277fe17d1235e915a7d8) Signed-off-by: Michael Niedermayer --- fftools/ffmpeg.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c index da4259a9a877f..f5029611965b3 100644 --- a/fftools/ffmpeg.c +++ b/fftools/ffmpeg.c @@ -2139,9 +2139,6 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) /* determine if the parameters for this input changed */ need_reinit = ifilter->format != frame->format; - if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || - (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) - need_reinit = 1; switch (ifilter->ist->st->codecpar->codec_type) { case AVMEDIA_TYPE_AUDIO: @@ -2155,6 +2152,13 @@ static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame) break; } + if (!ifilter->ist->reinit_filters && fg->graph) + need_reinit = 0; + + if (!!ifilter->hw_frames_ctx != !!frame->hw_frames_ctx || + (ifilter->hw_frames_ctx && ifilter->hw_frames_ctx->data != frame->hw_frames_ctx->data)) + need_reinit = 1; + if (need_reinit) { ret = ifilter_parameters_from_frame(ifilter, frame); if (ret < 0) From 89d65915cf6e7d79bd57896a4eb3fd626e699fc1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 9 Nov 2018 03:12:45 +0100 Subject: [PATCH 042/153] avcodec/pngdec: Check compression method method 0 (inflate/deflate) is the only specified in the specification and the only supported Fixes: Timeout Fixes: 10976/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PNG_fuzzer-5729372588736512 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 1f99674ddddcc33f4c37def0a206e31ad7c4c1af) Signed-off-by: Michael Niedermayer --- libavcodec/pngdec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c index 01144680f200b..189bb9a4c1733 100644 --- a/libavcodec/pngdec.c +++ b/libavcodec/pngdec.c @@ -578,6 +578,10 @@ static int decode_ihdr_chunk(AVCodecContext *avctx, PNGDecContext *s, } s->color_type = bytestream2_get_byte(&s->gb); s->compression_type = bytestream2_get_byte(&s->gb); + if (s->compression_type) { + av_log(avctx, AV_LOG_ERROR, "Invalid compression method %d\n", s->compression_type); + goto error; + } s->filter_type = bytestream2_get_byte(&s->gb); s->interlace_type = bytestream2_get_byte(&s->gb); bytestream2_skip(&s->gb, 4); /* crc */ From ab744447e141ecb997c0f01d7242a8aeb824f333 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Nov 2018 00:38:53 +0100 Subject: [PATCH 043/153] avcodec/truemotion2: fix integer overflows in tm2_low_chroma() Fixes: 11295/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TRUEMOTION2_fuzzer-4888953459572736 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 2ae39d795613f3c6925c59852b625029b747fe42) Signed-off-by: Michael Niedermayer --- libavcodec/truemotion2.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index 58a577f53c75a..c583ff403218c 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -484,7 +484,7 @@ static inline void tm2_high_chroma(int *data, int stride, int *last, unsigned *C } } -static inline void tm2_low_chroma(int *data, int stride, int *clast, int *CD, int *deltas, int bx) +static inline void tm2_low_chroma(int *data, int stride, int *clast, unsigned *CD, int *deltas, int bx) { int t; int l; @@ -494,8 +494,8 @@ static inline void tm2_low_chroma(int *data, int stride, int *clast, int *CD, in prev = clast[-3]; else prev = 0; - t = (CD[0] + CD[1]) >> 1; - l = (prev - CD[0] - CD[1] + clast[1]) >> 1; + t = (int)(CD[0] + CD[1]) >> 1; + l = (int)(prev - CD[0] - CD[1] + clast[1]) >> 1; CD[1] = CD[0] + CD[1] - t; CD[0] = t; clast[0] = l; From ee349bd0fd5acae9eb3bc142c93aedbf0dffee3c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 23 Nov 2018 02:33:04 +0100 Subject: [PATCH 044/153] avcodec/tiff: Limit filtering to decoded data MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: Timeout Fixes: 11068/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-5698456681709568 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer (cherry picked from commit 90ac0e5f29ba4730cd92d3268938b3730823e52b) Signed-off-by: Michael Niedermayer --- libavcodec/tiff.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index b537ec06a5f0c..d5b88923fd575 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -1304,6 +1304,7 @@ static int decode_frame(AVCodecContext *avctx, planes = s->planar ? s->bppcount : 1; for (plane = 0; plane < planes; plane++) { int remaining = avpkt->size; + int decoded_height; stride = p->linesize[plane]; dst = p->data[plane]; for (i = 0; i < s->height; i += s->rps) { @@ -1331,6 +1332,8 @@ static int decode_frame(AVCodecContext *avctx, break; } } + decoded_height = FFMIN(i, s->height); + if (s->predictor == 2) { if (s->photometric == TIFF_PHOTOMETRIC_YCBCR) { av_log(s->avctx, AV_LOG_ERROR, "predictor == 2 with YUV is unsupported"); @@ -1347,7 +1350,7 @@ static int decode_frame(AVCodecContext *avctx, s->avctx->pix_fmt == AV_PIX_FMT_YA16LE || s->avctx->pix_fmt == AV_PIX_FMT_GBRP16LE || s->avctx->pix_fmt == AV_PIX_FMT_GBRAP16LE) { - for (i = 0; i < s->height; i++) { + for (i = 0; i < decoded_height; i++) { for (j = soff; j < ssize; j += 2) AV_WL16(dst + j, AV_RL16(dst + j) + AV_RL16(dst + j - soff)); dst += stride; @@ -1358,13 +1361,13 @@ static int decode_frame(AVCodecContext *avctx, s->avctx->pix_fmt == AV_PIX_FMT_YA16BE || s->avctx->pix_fmt == AV_PIX_FMT_GBRP16BE || s->avctx->pix_fmt == AV_PIX_FMT_GBRAP16BE) { - for (i = 0; i < s->height; i++) { + for (i = 0; i < decoded_height; i++) { for (j = soff; j < ssize; j += 2) AV_WB16(dst + j, AV_RB16(dst + j) + AV_RB16(dst + j - soff)); dst += stride; } } else { - for (i = 0; i < s->height; i++) { + for (i = 0; i < decoded_height; i++) { for (j = soff; j < ssize; j++) dst[j] += dst[j - soff]; dst += stride; From 4fe90900d82aa14ea9e79dc05b8f174f92cfe4dc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 14 Nov 2018 09:42:44 +0100 Subject: [PATCH 045/153] avcodec/diracdec: Check component quant Fixes: Timeout Fixes: 10708/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DIRAC_fuzzer-5730140957442048 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 28c96c2ce2781c2cd147a9f3c299e18ce1dc7ff8) Signed-off-by: Michael Niedermayer --- libavcodec/diracdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/diracdec.c b/libavcodec/diracdec.c index af561d1426526..fd2313906219c 100644 --- a/libavcodec/diracdec.c +++ b/libavcodec/diracdec.c @@ -676,6 +676,11 @@ static int decode_component(DiracContext *s, int comp) b->length = get_interleaved_ue_golomb(&s->gb); if (b->length) { b->quant = get_interleaved_ue_golomb(&s->gb); + if (b->quant > (DIRAC_MAX_QUANT_INDEX - 1)) { + av_log(s->avctx, AV_LOG_ERROR, "Unsupported quant %d\n", b->quant); + b->quant = 0; + return AVERROR_INVALIDDATA; + } align_get_bits(&s->gb); b->coeff_data = s->gb.buffer + get_bits_count(&s->gb)/8; b->length = FFMIN(b->length, FFMAX(get_bits_left(&s->gb)/8, 0)); From 90db1e441fcd927a76690a7acf3f3225583d7b4e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 17 Nov 2018 09:24:30 +0100 Subject: [PATCH 046/153] avcodec/truemotion2rt: Fix rounding in input size check Fixes: Timeout Fixes: 11332/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TRUEMOTION2RT_fuzzer-5678456612847616 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 7f22a4ebc97817fd0968f5ea8295c9a59a6292e0) Signed-off-by: Michael Niedermayer --- libavcodec/truemotion2rt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/truemotion2rt.c b/libavcodec/truemotion2rt.c index 9df0b527bbdfb..e3ab998fda7cb 100644 --- a/libavcodec/truemotion2rt.c +++ b/libavcodec/truemotion2rt.c @@ -116,7 +116,7 @@ static int truemotion2rt_decode_frame(AVCodecContext *avctx, void *data, if (ret < 0) return ret; - if (avctx->width / s->hscale * avctx->height * s->delta_size > avpkt->size * 8LL * 4) + if ((avctx->width + s->hscale - 1)/ s->hscale * avctx->height * s->delta_size > avpkt->size * 8LL * 4) return AVERROR_INVALIDDATA; ret = init_get_bits8(gb, avpkt->data + ret, avpkt->size - ret); From eee0cf487aade926af27d7ffb079201ef5e8287e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 29 Nov 2018 02:32:10 +0100 Subject: [PATCH 047/153] avcodec/msmpeg4dec: Skip frame if its smaller than 1/8 of the minimal size Frames that small are not valid and of limited use for error concealment, while being very computationally intensive to process. Fixes: Timeout Fixes: 11318/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MSMPEG4V1_fuzzer-5710884555456512 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 09ec182864d41c990bc18f620eabb77444aeff57) Signed-off-by: Michael Niedermayer --- libavcodec/msmpeg4dec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/msmpeg4dec.c b/libavcodec/msmpeg4dec.c index 457a37e745806..16b67192b51ee 100644 --- a/libavcodec/msmpeg4dec.c +++ b/libavcodec/msmpeg4dec.c @@ -412,6 +412,14 @@ int ff_msmpeg4_decode_picture_header(MpegEncContext * s) { int code; + // at minimum one bit per macroblock is required at least in a valid frame, + // we discard frames much smaller than this. Frames smaller than 1/8 of the + // smallest "black/skip" frame generally contain not much recoverable content + // while at the same time they have the highest computational requirements + // per byte + if (get_bits_left(&s->gb) * 8LL < (s->width+15)/16 * ((s->height+15)/16)) + return AVERROR_INVALIDDATA; + if(s->msmpeg4_version==1){ int start_code = get_bits_long(&s->gb, 32); if(start_code!=0x00000100){ From 1a5db666ace66a4ebc42557753d09426df561923 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 27 Nov 2018 23:37:03 +0100 Subject: [PATCH 048/153] avcodec/wmv2dec: Skip I frame if its smaller than 1/8 of the minimal size Frames that small are not valid and of limited use for error concealment, while being very computationally intensive to process. Fixes: Timeout Fixes: 11168/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WMV2_fuzzer-5733782032744448 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit d6f4341522c3eafb046c47b115d79ce684a899fc) Signed-off-by: Michael Niedermayer --- libavcodec/wmv2dec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libavcodec/wmv2dec.c b/libavcodec/wmv2dec.c index 4f97d9227ce1e..92daa1639e5e9 100644 --- a/libavcodec/wmv2dec.c +++ b/libavcodec/wmv2dec.c @@ -181,6 +181,14 @@ int ff_wmv2_decode_secondary_picture_header(MpegEncContext *s) } s->dc_table_index = get_bits1(&s->gb); + + // at minimum one bit per macroblock is required at least in a valid frame, + // we discard frames much smaller than this. Frames smaller than 1/8 of the + // smallest "black/skip" frame generally contain not much recoverable content + // while at the same time they have the highest computational requirements + // per byte + if (get_bits_left(&s->gb) * 8LL < (s->width+15)/16 * ((s->height+15)/16)) + return AVERROR_INVALIDDATA; } s->inter_intra_pred = 0; s->no_rounding = 1; From 558ba71de5c75bd7d2cced51361180baaf32cfd7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 1 Dec 2018 22:16:19 +0100 Subject: [PATCH 049/153] avcodec/msvideo1: Check for too small dimensions Such low resolution would result in empty output as a minimum of 4x4 is needed We could also check for multiple of 4 dimensions but that is not needed Fixes: Timeout Fixes: 11191/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MSVIDEO1_fuzzer-5739529588178944 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 953bd58861ad933e614510140b05a61e3d1375be) Signed-off-by: Michael Niedermayer --- libavcodec/msvideo1.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/msvideo1.c b/libavcodec/msvideo1.c index 29700f54b66e9..de048d8b6fb9a 100644 --- a/libavcodec/msvideo1.c +++ b/libavcodec/msvideo1.c @@ -62,6 +62,9 @@ static av_cold int msvideo1_decode_init(AVCodecContext *avctx) s->avctx = avctx; + if (avctx->width < 4 || avctx->height < 4) + return AVERROR_INVALIDDATA; + /* figure out the colorspace based on the presence of a palette */ if (s->avctx->bits_per_coded_sample == 8) { s->mode_8bit = 1; From 55c36d2498119b3a01337115b28be006602ccb44 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 4 Dec 2018 16:29:40 +0100 Subject: [PATCH 050/153] avcodec/ppc/hevcdsp: Fix build failures with powerpc-linux-gnu-gcc-4.8 with --disable-optimizations The affected functions could also be changed into macros, this is the smaller change to fix it though. And avoids (probably) less readable macros The extra code should be optimized out when optimizations are done as all values are known at build after inlining. Signed-off-by: Michael Niedermayer (cherry picked from commit 2c64a6bcd280c64997e6c4799bc89c0a9393bbf3) Signed-off-by: Michael Niedermayer --- libavcodec/ppc/hevcdsp.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/libavcodec/ppc/hevcdsp.c b/libavcodec/ppc/hevcdsp.c index dcae43305a678..c1d562a4094aa 100644 --- a/libavcodec/ppc/hevcdsp.c +++ b/libavcodec/ppc/hevcdsp.c @@ -58,7 +58,13 @@ static av_always_inline void transform4x4(vec_s16 src_01, vec_s16 src_23, e1 = vec_msums(src_02, trans4[2], zero); o1 = vec_msums(src_13, trans4[3], zero); - add = vec_sl(vec_splat_s32(1), vec_splat_u32(shift - 1)); + switch(shift) { + case 7: add = vec_sl(vec_splat_s32(1), vec_splat_u32( 7 - 1)); break; + case 10: add = vec_sl(vec_splat_s32(1), vec_splat_u32(10 - 1)); break; + case 12: add = vec_sl(vec_splat_s32(1), vec_splat_u32(12 - 1)); break; + default: abort(); + } + e0 = vec_add(e0, add); e1 = vec_add(e1, add); @@ -72,7 +78,14 @@ static av_always_inline void scale(vec_s32 res[4], vec_s16 res_packed[2], const int shift) { int i; - vec_u32 v_shift = vec_splat_u32(shift); + vec_u32 v_shift; + + switch(shift) { + case 7: v_shift = vec_splat_u32(7) ; break; + case 10: v_shift = vec_splat_u32(10); break; + case 12: v_shift = vec_splat_u32(12); break; + default: abort(); + } for (i = 0; i < 4; i++) res[i] = vec_sra(res[i], v_shift); From 219cbc55277ab64b305c82bfa1f85e919610f81d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 1 Dec 2018 21:41:01 +0100 Subject: [PATCH 051/153] avcodec/dxv: Check that there is enough data to decompress Fixes: Timeout Fixes: 10979/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DXV_fuzzer-6178582203203584 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 2bc3811c0d6b34e43a55a7541722761f548628d0) Signed-off-by: Michael Niedermayer --- libavcodec/dxv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/dxv.c b/libavcodec/dxv.c index 08aca73b1fd8b..bf53d7d70622f 100644 --- a/libavcodec/dxv.c +++ b/libavcodec/dxv.c @@ -1192,6 +1192,12 @@ static int dxv_decode(AVCodecContext *avctx, void *data, ret = decompress_tex(avctx); if (ret < 0) return ret; + { + int w_block = avctx->coded_width / ctx->texture_block_w; + int h_block = avctx->coded_height / ctx->texture_block_h; + if (w_block * h_block * ctx->tex_step > ctx->tex_size * 8LL) + return AVERROR_INVALIDDATA; + } tframe.f = data; ret = ff_thread_get_buffer(avctx, &tframe, 0); From 9b5a6bb67ba35b3442667964f9e3a7e330b10bdc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 5 Dec 2018 02:18:51 +0100 Subject: [PATCH 052/153] avcodec/rasc: Check input space before reading chunk Fixes: Timeout Fixes: 11118/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RASC_fuzzer-5652564066959360 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 52ba824c65817c1db6aad41c470dde7162252036) Signed-off-by: Michael Niedermayer --- libavcodec/rasc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/rasc.c b/libavcodec/rasc.c index e8e0740ddd5f3..67351dfd19a6d 100644 --- a/libavcodec/rasc.c +++ b/libavcodec/rasc.c @@ -680,6 +680,9 @@ static int decode_frame(AVCodecContext *avctx, while (bytestream2_get_bytes_left(gb) > 0) { unsigned type, size = 0; + if (bytestream2_get_bytes_left(gb) < 8) + return AVERROR_INVALIDDATA; + type = bytestream2_get_le32(gb); if (type == KBND || type == BNDL) { intra = type == KBND; From 228f17ced3bd394677f0421f462067a0f287ca8c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 6 Dec 2018 01:19:37 +0100 Subject: [PATCH 053/153] avcodec/clearvideo: Check remaining input bits in P macro block loop Fixes: Timeout Fixes: 11083/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CLEARVIDEO_fuzzer-5657180351496192 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 7aaab127bebb33003105a620736d6cae8c45a6e5) Signed-off-by: Michael Niedermayer --- libavcodec/clearvideo.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index 0e3c772123111..ad3012f7b789f 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -570,6 +570,8 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data, for (j = 0; j < c->pmb_height; j++) { for (i = 0; i < c->pmb_width; i++) { + if (get_bits_left(&c->gb) <= 0) + return AVERROR_INVALIDDATA; if (get_bits1(&c->gb)) { MV mv = mvi_predict(&c->mvi, i, j, zero_mv); From 54fbdacc3791a6c5ff5945b139c7221d466676b5 Mon Sep 17 00:00:00 2001 From: chcunningham Date: Thu, 13 Dec 2018 13:58:40 -0800 Subject: [PATCH 054/153] lavf/mov: ensure only one tkhd per trak Chromium fuzzing produced a whacky file with extra tkhds. This caused an AVStream that was already in use to be corrupted by assigning it a new id, which blows up later in mov_read_trun because the MOVFragmentStreamInfo.index_entry now points OOB. Reviewed-by: Baptiste Coudurier Signed-off-by: Michael Niedermayer (cherry picked from commit c9f7b6f7a9fdffa0ab8f3aa84a1f701cf5b3a6e9) Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index ec57a05803301..6f92742e2353f 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1326,6 +1326,10 @@ static int update_frag_index(MOVContext *c, int64_t offset) return -1; for (i = 0; i < c->fc->nb_streams; i++) { + // Avoid building frag index if streams lack track id. + if (c->fc->streams[i]->id < 0) + return AVERROR_INVALIDDATA; + frag_stream_info[i].id = c->fc->streams[i]->id; frag_stream_info[i].sidx_pts = AV_NOPTS_VALUE; frag_stream_info[i].tfdt_dts = AV_NOPTS_VALUE; @@ -4154,7 +4158,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) st = avformat_new_stream(c->fc, NULL); if (!st) return AVERROR(ENOMEM); - st->id = c->fc->nb_streams; + st->id = -1; sc = av_mallocz(sizeof(MOVStreamContext)); if (!sc) return AVERROR(ENOMEM); @@ -4438,6 +4442,11 @@ static int mov_read_tkhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) st = c->fc->streams[c->fc->nb_streams-1]; sc = st->priv_data; + // Each stream (trak) should have exactly 1 tkhd. This catches bad files and + // avoids corrupting AVStreams mapped to an earlier tkhd. + if (st->id != -1) + return AVERROR_INVALIDDATA; + version = avio_r8(pb); flags = avio_rb24(pb); st->disposition |= (flags & MOV_TKHD_FLAG_ENABLED) ? AV_DISPOSITION_DEFAULT : 0; @@ -4704,6 +4713,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) break; } } + av_assert0(index_entry_pos <= st->nb_index_entries); avio_r8(pb); /* version */ flags = avio_rb24(pb); From f5859d4a8ee22f73d75d6b498d459700b034dd55 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 14 Dec 2018 21:52:09 +0100 Subject: [PATCH 055/153] avformat/nutenc: Document trailer index assert better Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 3a95b73abc868995b08ca2b4d8bbf2cda43184f8) Signed-off-by: Michael Niedermayer --- libavformat/nutenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/nutenc.c b/libavformat/nutenc.c index a92ff55c01373..e9a3bb49db01b 100644 --- a/libavformat/nutenc.c +++ b/libavformat/nutenc.c @@ -1172,7 +1172,7 @@ static int nut_write_trailer(AVFormatContext *s) ret = avio_open_dyn_buf(&dyn_bc); if (ret >= 0 && nut->sp_count) { - av_assert1(nut->write_index); + av_assert1(nut->write_index); // sp_count should be 0 if no index is going to be written write_index(nut, dyn_bc); put_packet(nut, bc, dyn_bc, 1, INDEX_STARTCODE); } From 321c418b8715e9b3142648561dcd1fd6494a9d62 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 15 Dec 2018 00:10:17 +0100 Subject: [PATCH 056/153] avcodec/rasc: Check that the number of moves is less than or equal the number of pixels Fixes: OOM Fixes: 10307/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RASC_fuzzer-5393974559244288 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 092cb17983b2660b4e050a05c739060f8e03d27a) Signed-off-by: Michael Niedermayer --- libavcodec/rasc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/rasc.c b/libavcodec/rasc.c index 67351dfd19a6d..1b607ac31ea65 100644 --- a/libavcodec/rasc.c +++ b/libavcodec/rasc.c @@ -215,7 +215,7 @@ static int decode_move(AVCodecContext *avctx, bytestream2_skip(gb, 8); compression = bytestream2_get_le32(gb); - if (nb_moves > INT32_MAX / 16) + if (nb_moves > INT32_MAX / 16 || nb_moves > avctx->width * avctx->height) return AVERROR_INVALIDDATA; uncompressed_size = 16 * nb_moves; From 45f5f2086ebe838b2aad7fa394fb1a2a31952ee8 Mon Sep 17 00:00:00 2001 From: chcunningham Date: Fri, 14 Dec 2018 13:44:07 -0800 Subject: [PATCH 057/153] lavf/id3v2: fail read_apic on EOF reading mimetype MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit avio_read may return EOF, leaving the mimetype array unitialized. fail early when this occurs to avoid using the array in an unitialized state. Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer (cherry picked from commit ee1e39a576977fd38c3b94fc56125d31d38833e9) Signed-off-by: Michael Niedermayer --- libavformat/id3v2.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavformat/id3v2.c b/libavformat/id3v2.c index f7de26a1d8e54..5fe055b591a81 100644 --- a/libavformat/id3v2.c +++ b/libavformat/id3v2.c @@ -590,7 +590,7 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, int isv34) { int enc, pic_type; - char mimetype[64]; + char mimetype[64] = {0}; const CodecMime *mime = ff_id3v2_mime_tags; enum AVCodecID id = AV_CODEC_ID_NONE; ID3v2ExtraMetaAPIC *apic = NULL; @@ -612,7 +612,9 @@ static void read_apic(AVFormatContext *s, AVIOContext *pb, int taglen, if (isv34) { taglen -= avio_get_str(pb, taglen, mimetype, sizeof(mimetype)); } else { - avio_read(pb, mimetype, 3); + if (avio_read(pb, mimetype, 3) < 0) + goto fail; + mimetype[3] = 0; taglen -= 3; } From e1f40f0dae68ba82cd955fafd82aec336a81d27d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 18 Dec 2018 14:27:48 +0100 Subject: [PATCH 058/153] avcodec/mjpegdec: Fix indention of ljpeg_decode_yuv_scan() Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit ea30ac1e408246382796f61d645d1e087aed390a) Signed-off-by: Michael Niedermayer --- libavcodec/mjpegdec.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/libavcodec/mjpegdec.c b/libavcodec/mjpegdec.c index b0cb3ffc83925..53598fdb3c6c9 100644 --- a/libavcodec/mjpegdec.c +++ b/libavcodec/mjpegdec.c @@ -1206,25 +1206,25 @@ static int ljpeg_decode_yuv_scan(MJpegDecodeContext *s, int predictor, || v * mb_y + y >= s->height) { // Nothing to do } else if (bits<=8) { - ptr = s->picture_ptr->data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap - if(y==0 && toprow){ - if(x==0 && leftcol){ - pred= 1 << (bits - 1); - }else{ - pred= ptr[-1]; - } - }else{ - if(x==0 && leftcol){ - pred= ptr[-linesize]; + ptr = s->picture_ptr->data[c] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap + if(y==0 && toprow){ + if(x==0 && leftcol){ + pred= 1 << (bits - 1); + }else{ + pred= ptr[-1]; + } }else{ - PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); + if(x==0 && leftcol){ + pred= ptr[-linesize]; + }else{ + PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); + } } - } - if (s->interlaced && s->bottom_field) - ptr += linesize >> 1; - pred &= mask; - *ptr= pred + ((unsigned)dc << point_transform); + if (s->interlaced && s->bottom_field) + ptr += linesize >> 1; + pred &= mask; + *ptr= pred + ((unsigned)dc << point_transform); }else{ ptr16 = (uint16_t*)(s->picture_ptr->data[c] + 2*(linesize * (v * mb_y + y)) + 2*(h * mb_x + x)); //FIXME optimize this crap if(y==0 && toprow){ From 2f75965c47da0a25ec03a8aebd565fba20aa317b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 6 Dec 2018 21:51:22 +0100 Subject: [PATCH 059/153] tests/fate/filter-video: increase fuzz for fate-filter-refcmp-psnr-rgb Fixes: test failure on powerpc Signed-off-by: Michael Niedermayer (cherry picked from commit f8f762c300e29d80ece363edc08e137b371d909f) Signed-off-by: Michael Niedermayer --- tests/fate/filter-video.mak | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fate/filter-video.mak b/tests/fate/filter-video.mak index 8bbdc0489690a..1042e96e54b0b 100644 --- a/tests/fate/filter-video.mak +++ b/tests/fate/filter-video.mak @@ -782,7 +782,7 @@ fate-filter-meta-4560-rotate0: CMD = framecrc -flags +bitexact -c:a aac_fixed -i REFCMP_DEPS = FFMPEG LAVFI_INDEV TESTSRC2_FILTER AVGBLUR_FILTER METADATA_FILTER FATE_FILTER_SAMPLES-$(call ALLYES, $(REFCMP_DEPS) PSNR_FILTER) += fate-filter-refcmp-psnr-rgb -fate-filter-refcmp-psnr-rgb: CMD = refcmp_metadata psnr rgb24 0.001 +fate-filter-refcmp-psnr-rgb: CMD = refcmp_metadata psnr rgb24 0.002 FATE_FILTER_SAMPLES-$(call ALLYES, $(REFCMP_DEPS) PSNR_FILTER) += fate-filter-refcmp-psnr-yuv fate-filter-refcmp-psnr-yuv: CMD = refcmp_metadata psnr yuv422p 0.0015 From e3fbbb7d18b6a19a55ce4f2662e726e41d330553 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 7 Dec 2018 21:51:48 +0100 Subject: [PATCH 060/153] avformat/mpegts: Fix side data type for stream id Signed-off-by: Michael Niedermayer (cherry picked from commit ab1319d82f0c77308792fa2d88cbfc73c3e47cb7) Signed-off-by: Michael Niedermayer --- libavformat/mpegts.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mpegts.c b/libavformat/mpegts.c index edf6b5701df48..a5e850e121c8e 100644 --- a/libavformat/mpegts.c +++ b/libavformat/mpegts.c @@ -918,7 +918,7 @@ static void new_data_packet(const uint8_t *buffer, int len, AVPacket *pkt) static int new_pes_packet(PESContext *pes, AVPacket *pkt) { - char *sd; + uint8_t *sd; av_init_packet(pkt); From 42357b37cb9d5960907ccf74972de3a9cf826703 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 7 Dec 2018 21:52:30 +0100 Subject: [PATCH 061/153] avcodec/avcodec: Document the data type for AV_PKT_DATA_MPEGTS_STREAM_ID Signed-off-by: Michael Niedermayer (cherry picked from commit 68e011e4103b9cb5ac2d152d73ca8393065a33fb) Signed-off-by: Michael Niedermayer --- libavcodec/avcodec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 7ffef768dca2f..bee2234575cdf 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1321,7 +1321,7 @@ enum AVPacketSideDataType { AV_PKT_DATA_METADATA_UPDATE, /** - * MPEGTS stream ID, this is required to pass the stream ID + * MPEGTS stream ID as uint8_t, this is required to pass the stream ID * information from the demuxer to the corresponding muxer. */ AV_PKT_DATA_MPEGTS_STREAM_ID, From 4c0be3a60cf862656d276443fb0ca1bfcfa7bdc2 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Dec 2018 19:04:56 +0100 Subject: [PATCH 062/153] avcodec/rpza: Move frame allocation to a later point This will allow performing some fast checks before the slow allocation Signed-off-by: Michael Niedermayer (cherry picked from commit 8a708aa99cb0e8d76e52117b1fd89d221f0055e9) Signed-off-by: Michael Niedermayer --- libavcodec/rpza.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/libavcodec/rpza.c b/libavcodec/rpza.c index b71ebd1cbe946..cffbfe441652c 100644 --- a/libavcodec/rpza.c +++ b/libavcodec/rpza.c @@ -73,13 +73,12 @@ typedef struct RpzaContext { static int rpza_decode_stream(RpzaContext *s) { int width = s->avctx->width; - int stride = s->frame->linesize[0] / 2; - int row_inc = stride - 4; + int stride, row_inc, ret; int chunk_size; uint16_t colorA = 0, colorB; uint16_t color4[4]; uint16_t ta, tb; - uint16_t *pixels = (uint16_t *)s->frame->data[0]; + uint16_t *pixels; int row_ptr = 0; int pixel_ptr = 0; @@ -106,6 +105,12 @@ static int rpza_decode_stream(RpzaContext *s) /* Number of 4x4 blocks in frame. */ total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4); + if ((ret = ff_reget_buffer(s->avctx, s->frame)) < 0) + return ret; + pixels = (uint16_t *)s->frame->data[0]; + stride = s->frame->linesize[0] / 2; + row_inc = stride - 4; + /* Process chunk data */ while (bytestream2_get_bytes_left(&s->gb)) { uint8_t opcode = bytestream2_get_byte(&s->gb); /* Get opcode */ @@ -256,9 +261,6 @@ static int rpza_decode_frame(AVCodecContext *avctx, bytestream2_init(&s->gb, avpkt->data, avpkt->size); - if ((ret = ff_reget_buffer(avctx, s->frame)) < 0) - return ret; - ret = rpza_decode_stream(s); if (ret < 0) return ret; From c22b67feaae9f6b5a9ebbbb84d64ff749f084135 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Dec 2018 19:13:27 +0100 Subject: [PATCH 063/153] avcodec/rpza: Check that there is enough data for all the blocks Fixes: Timeout Fixes: 11547/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RPZA_fuzzer-5678435842654208 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit e63517e00a1a8375c7fb3b8c4c64c9a7c3da713e) Signed-off-by: Michael Niedermayer --- libavcodec/rpza.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/rpza.c b/libavcodec/rpza.c index cffbfe441652c..8e1efa24450ef 100644 --- a/libavcodec/rpza.c +++ b/libavcodec/rpza.c @@ -105,6 +105,9 @@ static int rpza_decode_stream(RpzaContext *s) /* Number of 4x4 blocks in frame. */ total_blocks = ((s->avctx->width + 3) / 4) * ((s->avctx->height + 3) / 4); + if (total_blocks / 32 > bytestream2_get_bytes_left(&s->gb)) + return AVERROR_INVALIDDATA; + if ((ret = ff_reget_buffer(s->avctx, s->frame)) < 0) return ret; pixels = (uint16_t *)s->frame->data[0]; From 73c90818b116e3783e6479172a565cfb9fa36036 Mon Sep 17 00:00:00 2001 From: Jacob Trimble Date: Wed, 19 Dec 2018 16:00:22 -0800 Subject: [PATCH 064/153] libavformat/mov: Fix NULL-dereference read for some encrypted content. When reading frames, we need to use the fragment for the correct stream. Sometimes the "current" fragment is not the same as the one the frame is for. Found by Chromium's ClusterFuzz: https://crbug.com/906392 and https://crbug.com/915524 Signed-off-by: Jacob Trimble Signed-off-by: Michael Niedermayer (cherry picked from commit 555f332e7adbd492ca74fa7329c492819b52e2ed) Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 6f92742e2353f..ff7fdd48e2756 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -6556,14 +6556,14 @@ static int cenc_decrypt(MOVContext *c, MOVStreamContext *sc, AVEncryptionInfo *s return 0; } -static int cenc_filter(MOVContext *mov, MOVStreamContext *sc, AVPacket *pkt, int current_index) +static int cenc_filter(MOVContext *mov, AVStream* st, MOVStreamContext *sc, AVPacket *pkt, int current_index) { MOVFragmentStreamInfo *frag_stream_info; MOVEncryptionIndex *encryption_index; AVEncryptionInfo *encrypted_sample; int encrypted_index, ret; - frag_stream_info = get_current_frag_stream_info(&mov->frag_index); + frag_stream_info = get_frag_stream_info(&mov->frag_index, mov->frag_index.current, st->id); encrypted_index = current_index; encryption_index = NULL; if (frag_stream_info) { @@ -7793,7 +7793,7 @@ static int mov_read_packet(AVFormatContext *s, AVPacket *pkt) if (mov->aax_mode) aax_filter(pkt->data, pkt->size, mov); - ret = cenc_filter(mov, sc, pkt, current_index); + ret = cenc_filter(mov, st, sc, pkt, current_index); if (ret < 0) return ret; From 69f50eb9150c3b587038e9742a0abdab57a94919 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 20 Dec 2018 22:40:05 +0100 Subject: [PATCH 065/153] postproc/postprocess_template: Avoid using %4 for the threshold compare This avoids problems if %4 is the stack pointer the constraints do not allow %4 to be the stack pointer but gcc 9 may no longer support specifying such constraints Signed-off-by: Michael Niedermayer (cherry picked from commit 4325527e1c4fd2da119e81933172065ee1274eda) Signed-off-by: Michael Niedermayer --- libpostproc/postprocess_template.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libpostproc/postprocess_template.c b/libpostproc/postprocess_template.c index 0a4398926681b..485eb5cfc0df7 100644 --- a/libpostproc/postprocess_template.c +++ b/libpostproc/postprocess_template.c @@ -1184,10 +1184,10 @@ FIND_MIN_MAX((%0, %1, 8)) #endif "movq %%mm6, %%mm0 \n\t" // max "psubb %%mm7, %%mm6 \n\t" // max - min - "push %4 \n\t" - "movd %%mm6, %k4 \n\t" - "cmpb "MANGLE(deringThreshold)", %b4 \n\t" - "pop %4 \n\t" + "push %%"FF_REG_a" \n\t" + "movd %%mm6, %%eax \n\t" + "cmpb "MANGLE(deringThreshold)", %%al \n\t" + "pop %%"FF_REG_a" \n\t" " jb 1f \n\t" PAVGB(%%mm0, %%mm7) // a=(max + min)/2 "punpcklbw %%mm7, %%mm7 \n\t" From daef9d43828733534267dd15975f761ce7277a5b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 20 Dec 2018 22:40:06 +0100 Subject: [PATCH 066/153] postproc/postprocess_template: remove FF_REG_sp from clobber list Future gcc may no longer support this Tested-by: James Almer Signed-off-by: Michael Niedermayer (cherry picked from commit c1cbeb87db4bfc6e281e4254a6c7fdd3854fc9b9) Signed-off-by: Michael Niedermayer --- libpostproc/postprocess_template.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libpostproc/postprocess_template.c b/libpostproc/postprocess_template.c index 485eb5cfc0df7..b0adfd168ccfa 100644 --- a/libpostproc/postprocess_template.c +++ b/libpostproc/postprocess_template.c @@ -1317,7 +1317,7 @@ DERING_CORE((%0, %1, 8) ,(%%FF_REGd, %1, 4),%%mm2,%%mm4,%%mm0,%%mm3,%%mm5, "1: \n\t" : : "r" (src), "r" ((x86_reg)stride), "m" (c->pQPb), "m"(c->pQPb2), "q"(tmp) NAMED_CONSTRAINTS_ADD(deringThreshold,b00,b02,b08) - : "%"FF_REG_a, "%"FF_REG_d, "%"FF_REG_sp + : "%"FF_REG_a, "%"FF_REG_d ); #else // HAVE_7REGS && (TEMPLATE_PP_MMXEXT || TEMPLATE_PP_3DNOW) int y; From 5550946ff4bdb4f6092e6aabd8d11888695ffbd0 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 9 Dec 2018 02:26:18 +0100 Subject: [PATCH 067/153] avcodec/ilbcdec: fix integer overflow in energy webrtc uses a int32_t like the existing code in ilbcdec Fixes: signed integer overflow: 2080245063 + 257939661 cannot be represented in type 'int' Fixes: 11037/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ILBC_fuzzer-5682976612941824 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit fbf409cd91aca2b4738c6b5bc963ae6041f26701) Signed-off-by: Michael Niedermayer --- libavcodec/ilbcdec.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/ilbcdec.c b/libavcodec/ilbcdec.c index 8a6dbe0b752ab..50012c02317ca 100644 --- a/libavcodec/ilbcdec.c +++ b/libavcodec/ilbcdec.c @@ -1303,7 +1303,8 @@ static int xcorr_coeff(int16_t *target, int16_t *regressor, pos += step; /* Do a +/- to get the next energy */ - energy += step * ((*rp_end * *rp_end - *rp_beg * *rp_beg) >> shifts); + energy += (unsigned)step * ((*rp_end * *rp_end - *rp_beg * *rp_beg) >> shifts); + rp_beg += step; rp_end += step; } From 5ed024e40bdbc0047d7cad38f6b7d52903dbc108 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 16 Dec 2018 21:43:07 +0100 Subject: [PATCH 068/153] avcodec/fic: Fail on invalid slice size/off Fixes: Timeout Fixes: 11486/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FIC_fuzzer-5677133863583744 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 30a7a81cdc2ee2eac6d3271439c43f11b7327b3e) Signed-off-by: Michael Niedermayer --- libavcodec/fic.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/fic.c b/libavcodec/fic.c index dcf0777674285..3e363463589cd 100644 --- a/libavcodec/fic.c +++ b/libavcodec/fic.c @@ -380,6 +380,8 @@ static int fic_decode_frame(AVCodecContext *avctx, void *data, slice_h = FFALIGN(avctx->height - ctx->slice_h * (nslices - 1), 16); } else { slice_size = AV_RB32(src + tsize + FIC_HEADER_SIZE + slice * 4 + 4); + if (slice_size < slice_off) + return AVERROR_INVALIDDATA; } if (slice_size < slice_off || slice_size > msize) From 929b5519d8e9fb0bada84a708c7b43bdb447574d Mon Sep 17 00:00:00 2001 From: gxw Date: Mon, 24 Dec 2018 14:07:44 +0800 Subject: [PATCH 069/153] avcodec/mips: Fix failed case: hevc-conformance-AMP_A_Samsung_* when enable msa The AV_INPUT_BUFFER_PADDING_SIZE has been increased to 64, but the value is still 32 in function ff_hevc_sao_edge_filter_8_msa. So, use AV_INPUT_BUFFER_PADDING_SIZE directly. Also, use MAX_PB_SIZE directly instead of 64. Fate tests passed. Reviewed-by: Derek Buitenhuis Signed-off-by: Michael Niedermayer (cherry picked from commit f652c7a45c60427db0a89fae665e63b546af6ebb) Signed-off-by: Michael Niedermayer --- libavcodec/mips/hevc_lpf_sao_msa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mips/hevc_lpf_sao_msa.c b/libavcodec/mips/hevc_lpf_sao_msa.c index 5b5537a264503..adcafde621167 100644 --- a/libavcodec/mips/hevc_lpf_sao_msa.c +++ b/libavcodec/mips/hevc_lpf_sao_msa.c @@ -2630,7 +2630,7 @@ void ff_hevc_sao_edge_filter_8_msa(uint8_t *dst, uint8_t *src, int16_t *sao_offset_val, int eo, int width, int height) { - ptrdiff_t stride_src = (2 * 64 + 32) / sizeof(uint8_t); + ptrdiff_t stride_src = (2 * MAX_PB_SIZE + AV_INPUT_BUFFER_PADDING_SIZE) / sizeof(uint8_t); switch (eo) { case 0: From ea279bd160d973e7bc765002fcc13d064d1d356d Mon Sep 17 00:00:00 2001 From: David Bryant Date: Tue, 20 Nov 2018 21:00:47 -0800 Subject: [PATCH 070/153] avformat/wvdec: detect and error out on WavPack DSD files Not currently supported. (cherry picked from commit db109373d87b1fa5fe9f3d027d1bb752f725b74a) Signed-off-by: Michael Niedermayer --- libavformat/wvdec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/wvdec.c b/libavformat/wvdec.c index 82526563ec18a..2060523c3bc51 100644 --- a/libavformat/wvdec.c +++ b/libavformat/wvdec.c @@ -40,6 +40,7 @@ enum WV_FLAGS { WV_HBAL = 0x0400, WV_MCINIT = 0x0800, WV_MCEND = 0x1000, + WV_DSD = 0x80000000, }; static const int wv_rates[16] = { @@ -97,6 +98,11 @@ static int wv_read_block_header(AVFormatContext *ctx, AVIOContext *pb) return ret; } + if (wc->header.flags & WV_DSD) { + avpriv_report_missing_feature(ctx, "WV DSD"); + return AVERROR_PATCHWELCOME; + } + if (wc->header.version < 0x402 || wc->header.version > 0x410) { avpriv_report_missing_feature(ctx, "WV version 0x%03X", wc->header.version); From 33b4aba5bdf43415aeb1aa3d51dc03a7cd62b2ee Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 28 Dec 2018 22:22:56 +0100 Subject: [PATCH 071/153] avcodec/mjpegbdec: Fix some misplaced {} and spaces Reviewed-by: Derek Buitenhuis Signed-off-by: Michael Niedermayer (cherry picked from commit 11a8d2ccab1fe165eef4578c048d38731dbe1d6f) Signed-off-by: Michael Niedermayer --- libavcodec/mjpegbdec.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/libavcodec/mjpegbdec.c b/libavcodec/mjpegbdec.c index a858707d54586..8583fcb4f9f53 100644 --- a/libavcodec/mjpegbdec.c +++ b/libavcodec/mjpegbdec.c @@ -70,8 +70,7 @@ static int mjpegb_decode_frame(AVCodecContext *avctx, skip_bits(&hgb, 32); /* reserved zeros */ - if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g')) - { + if (get_bits_long(&hgb, 32) != MKBETAG('m','j','p','g')) { av_log(avctx, AV_LOG_WARNING, "not mjpeg-b (bad fourcc)\n"); return AVERROR_INVALIDDATA; } @@ -85,19 +84,17 @@ static int mjpegb_decode_frame(AVCodecContext *avctx, dqt_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "dqt is %d and size is %d\n"); av_log(avctx, AV_LOG_DEBUG, "dqt offs: 0x%"PRIx32"\n", dqt_offs); - if (dqt_offs) - { + if (dqt_offs) { init_get_bits(&s->gb, buf_ptr+dqt_offs, (buf_end - (buf_ptr+dqt_offs))*8); s->start_code = DQT; if (ff_mjpeg_decode_dqt(s) < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) - return AVERROR_INVALIDDATA; + return AVERROR_INVALIDDATA; } dht_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "dht is %d and size is %d\n"); av_log(avctx, AV_LOG_DEBUG, "dht offs: 0x%"PRIx32"\n", dht_offs); - if (dht_offs) - { + if (dht_offs) { init_get_bits(&s->gb, buf_ptr+dht_offs, (buf_end - (buf_ptr+dht_offs))*8); s->start_code = DHT; ff_mjpeg_decode_dht(s); @@ -105,8 +102,7 @@ static int mjpegb_decode_frame(AVCodecContext *avctx, sof_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sof is %d and size is %d\n"); av_log(avctx, AV_LOG_DEBUG, "sof offs: 0x%"PRIx32"\n", sof_offs); - if (sof_offs) - { + if (sof_offs) { init_get_bits(&s->gb, buf_ptr+sof_offs, (buf_end - (buf_ptr+sof_offs))*8); s->start_code = SOF0; if (ff_mjpeg_decode_sof(s) < 0) @@ -117,25 +113,23 @@ static int mjpegb_decode_frame(AVCodecContext *avctx, av_log(avctx, AV_LOG_DEBUG, "sos offs: 0x%"PRIx32"\n", sos_offs); sod_offs = read_offs(avctx, &hgb, buf_end - buf_ptr, "sof is %d and size is %d\n"); av_log(avctx, AV_LOG_DEBUG, "sod offs: 0x%"PRIx32"\n", sod_offs); - if (sos_offs) - { + if (sos_offs) { init_get_bits(&s->gb, buf_ptr + sos_offs, 8 * FFMIN(field_size, buf_end - buf_ptr - sos_offs)); s->mjpb_skiptosod = (sod_offs - sos_offs - show_bits(&s->gb, 16)); s->start_code = SOS; if (ff_mjpeg_decode_sos(s, NULL, 0, NULL) < 0 && (avctx->err_recognition & AV_EF_EXPLODE)) - return AVERROR_INVALIDDATA; + return AVERROR_INVALIDDATA; } if (s->interlaced) { s->bottom_field ^= 1; /* if not bottom field, do not output image yet */ - if (s->bottom_field != s->interlace_polarity && second_field_offs) - { + if (s->bottom_field != s->interlace_polarity && second_field_offs) { buf_ptr = buf + second_field_offs; goto read_header; - } + } } //XXX FIXME factorize, this looks very similar to the EOI code From 41ee513c81a3741760532bad1a929b27b3dacf49 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 28 Dec 2018 22:22:53 +0100 Subject: [PATCH 072/153] avcodec/v4l2_m2m: fix cant typo Reviewed-by: Lou Logan Signed-off-by: Michael Niedermayer (cherry picked from commit 062bf5639359e183e016bcb795ac10735f83e863) Signed-off-by: Michael Niedermayer --- libavcodec/v4l2_m2m.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/v4l2_m2m.h b/libavcodec/v4l2_m2m.h index 452bf0d9bc258..0d4671beb1aa8 100644 --- a/libavcodec/v4l2_m2m.h +++ b/libavcodec/v4l2_m2m.h @@ -104,7 +104,7 @@ int ff_v4l2_m2m_codec_init(AVCodecContext *avctx); int ff_v4l2_m2m_codec_end(AVCodecContext *avctx); /** - * Reinitializes the V4L2m2mContext when the driver cant continue processing + * Reinitializes the V4L2m2mContext when the driver cannot continue processing * with the capture parameters. * * @param[in] ctx The V4L2m2mContext instantiated by the encoder/decoder. @@ -114,7 +114,7 @@ int ff_v4l2_m2m_codec_end(AVCodecContext *avctx); int ff_v4l2_m2m_codec_reinit(V4L2m2mContext *ctx); /** - * Reinitializes the V4L2m2mContext when the driver cant continue processing + * Reinitializes the V4L2m2mContext when the driver cannot continue processing * with the any of the current V4L2Contexts (ie, changes in output and capture). * * @param[in] ctx The V4L2m2mContext instantiated by the encoder/decoder. From 6b6c854658661573dbc598a1fc5921c5756dd6cd Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 28 Dec 2018 22:22:52 +0100 Subject: [PATCH 073/153] avformat/libopenmpt: Fix successfull typo Reviewed-by: Lou Logan Signed-off-by: Michael Niedermayer (cherry picked from commit 571af98a5959d72c65a6753eb8e82cde407f4cd0) Signed-off-by: Michael Niedermayer --- libavformat/libopenmpt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/libopenmpt.c b/libavformat/libopenmpt.c index 0fff702a36f46..a3342708477da 100644 --- a/libavformat/libopenmpt.c +++ b/libavformat/libopenmpt.c @@ -259,7 +259,7 @@ static int read_probe_openmpt(AVProbeData *p) } else { /* The file extension is unknown and we have very few data * bytes available. libopenmpt cannot decide anything here, - * and returning any score > 0 would result in successfull + * and returning any score > 0 would result in successful * probing of random data. */ return 0; From 15857674c51db30f6862bf5e643f06c9e64f3209 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 31 Dec 2018 18:11:44 +0100 Subject: [PATCH 074/153] avcodec/4xm: Fix returned error codes Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 07607a1db879d0d96e2c91e1354bc4e425937d3a) Signed-off-by: Michael Niedermayer --- libavcodec/4xm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/4xm.c b/libavcodec/4xm.c index 5547dfd87f223..8e05a4c366056 100644 --- a/libavcodec/4xm.c +++ b/libavcodec/4xm.c @@ -498,7 +498,7 @@ static int decode_i_block(FourXContext *f, int16_t *block) if (get_bits_left(&f->gb) < 2){ av_log(f->avctx, AV_LOG_ERROR, "%d bits left before decode_i_block()\n", get_bits_left(&f->gb)); - return -1; + return AVERROR_INVALIDDATA; } /* DC coef */ @@ -732,7 +732,7 @@ static int decode_i2_frame(FourXContext *f, const uint8_t *buf, int length) for (x = 0; x < width; x += 16) { unsigned int color[4] = { 0 }, bits; if (buf_end - buf < 8) - return -1; + return AVERROR_INVALIDDATA; // warning following is purely guessed ... color[0] = bytestream2_get_le16u(&g3); color[1] = bytestream2_get_le16u(&g3); From e385fc45dddc064dbc48c933d08cdedc764d15f4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 31 Dec 2018 20:45:17 +0100 Subject: [PATCH 075/153] doc/indevs: fix upto typo Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit b33de557470471fe5d3a07fb441ec3f548f1d50a) Signed-off-by: Michael Niedermayer --- doc/indevs.texi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/indevs.texi b/doc/indevs.texi index e1301ccf9743b..ba6a2ad02f9a0 100644 --- a/doc/indevs.texi +++ b/doc/indevs.texi @@ -374,7 +374,7 @@ Defaults to @option{false}. @item timestamp_align Capture start time alignment in seconds. If set to nonzero, input frames are dropped till the system timestamp aligns with configured value. -Alignment difference of upto one frame duration is tolerated. +Alignment difference of up to one frame duration is tolerated. This is useful for maintaining input synchronization across N different hardware devices deployed for 'N-way' redundancy. The system time of different hardware devices should be synchronized with protocols such as NTP or PTP, From 99576bf034ce283f1e7c48ba4898ca2e991b7286 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 31 Dec 2018 20:54:12 +0100 Subject: [PATCH 076/153] avfilter/vf_tonemap_opencl: Make static tables const Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 47c3a10b16f2721c7afa333869aafa8c007fb419) Signed-off-by: Michael Niedermayer --- libavfilter/vf_tonemap_opencl.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavfilter/vf_tonemap_opencl.c b/libavfilter/vf_tonemap_opencl.c index cd293c2522395..ae3f98d817007 100644 --- a/libavfilter/vf_tonemap_opencl.c +++ b/libavfilter/vf_tonemap_opencl.c @@ -98,12 +98,12 @@ static const struct LumaCoefficients luma_coefficients[AVCOL_SPC_NB] = { [AVCOL_SPC_BT2020_NCL] = { 0.2627, 0.6780, 0.0593 }, }; -static struct PrimaryCoefficients primaries_table[AVCOL_PRI_NB] = { +static const struct PrimaryCoefficients primaries_table[AVCOL_PRI_NB] = { [AVCOL_PRI_BT709] = { 0.640, 0.330, 0.300, 0.600, 0.150, 0.060 }, [AVCOL_PRI_BT2020] = { 0.708, 0.292, 0.170, 0.797, 0.131, 0.046 }, }; -static struct WhitepointCoefficients whitepoint_table[AVCOL_PRI_NB] = { +static const struct WhitepointCoefficients whitepoint_table[AVCOL_PRI_NB] = { [AVCOL_PRI_BT709] = { 0.3127, 0.3290 }, [AVCOL_PRI_BT2020] = { 0.3127, 0.3290 }, }; From 1623f42d993adb9fa2bb9f7c766b6ce55922a8d5 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 25 Dec 2018 18:41:58 +0100 Subject: [PATCH 077/153] avcodec/exr: Check for duplicate channel index Fixes: Out of memory Fixes: 11582/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_EXR_fuzzer-5730204559867904 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit f9728feaf90eb7493f8872356f54150efafb59cc) Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 5253cc3f136c7..13755e1e6eec2 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1463,6 +1463,11 @@ static int decode_header(EXRContext *s, AVFrame *frame) } s->pixel_type = current_pixel_type; s->channel_offsets[channel_index] = s->current_channel_offset; + } else if (channel_index >= 0) { + av_log(s->avctx, AV_LOG_ERROR, + "Multiple channels with index %d.\n", channel_index); + ret = AVERROR_INVALIDDATA; + goto fail; } s->channels = av_realloc(s->channels, From 9239d58b3653c876004b49995a8b698327f7cf87 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 25 Dec 2018 21:30:54 +0100 Subject: [PATCH 078/153] avcodec/exr: set layer_match in all branches Otherwise it is left to the value from the previous iteration Signed-off-by: Michael Niedermayer (cherry picked from commit 433d2ae4353f3c513a45780845d9d8ca252cd4dc) Signed-off-by: Michael Niedermayer --- libavcodec/exr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/exr.c b/libavcodec/exr.c index 13755e1e6eec2..0f8b0fda9f2c8 100644 --- a/libavcodec/exr.c +++ b/libavcodec/exr.c @@ -1389,6 +1389,7 @@ static int decode_header(EXRContext *s, AVFrame *frame) if (*ch_gb.buffer == '.') ch_gb.buffer++; /* skip dot if not given */ } else { + layer_match = 0; av_log(s->avctx, AV_LOG_INFO, "Channel doesn't match layer : %s.\n", ch_gb.buffer); } From c694273feb813263122f121eae7c3c881cbf13ba Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 4 Jan 2019 20:00:38 +0100 Subject: [PATCH 079/153] avcodec/h264_slice: Fix integer overflow in implicit_weight_table() Fixes: signed integer overflow: 2 * 2132811760 cannot be represented in type 'int' Fixes: 11156/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_H264_fuzzer-6237685933408256 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 77e56d74f972537aecd5bc2c5c4111e1d6ad0963) Signed-off-by: Michael Niedermayer --- libavcodec/h264_slice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/h264_slice.c b/libavcodec/h264_slice.c index 2e158745a02ba..1c9a270fb6cb2 100644 --- a/libavcodec/h264_slice.c +++ b/libavcodec/h264_slice.c @@ -678,7 +678,7 @@ static void implicit_weight_table(const H264Context *h, H264SliceContext *sl, in cur_poc = h->cur_pic_ptr->field_poc[h->picture_structure - 1]; } if (sl->ref_count[0] == 1 && sl->ref_count[1] == 1 && !FRAME_MBAFF(h) && - sl->ref_list[0][0].poc + (int64_t)sl->ref_list[1][0].poc == 2 * cur_poc) { + sl->ref_list[0][0].poc + (int64_t)sl->ref_list[1][0].poc == 2LL * cur_poc) { sl->pwt.use_weight = 0; sl->pwt.use_weight_chroma = 0; return; From 792df36f42ab2f5c61281f428bb3a2af2cfef70b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 4 Jan 2019 19:51:04 +0100 Subject: [PATCH 080/153] avcodec/gdv: Optimize and factorize scaling loops Fixes: Timeout Fixes: 11067/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_GDV_fuzzer-5686623711264768 Before change: Executed clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_GDV_fuzzer-5686623711264768 in 34386 ms After change: Executed clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_GDV_fuzzer-5686623711264768 in 24327 ms Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 6e23736aefa83859fdb6faae4fd14c169f1a41ab) Signed-off-by: Michael Niedermayer --- libavcodec/gdv.c | 87 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/libavcodec/gdv.c b/libavcodec/gdv.c index 538bc38e3eadf..a29de28aa144f 100644 --- a/libavcodec/gdv.c +++ b/libavcodec/gdv.c @@ -72,9 +72,64 @@ static av_cold int gdv_decode_init(AVCodecContext *avctx) return 0; } +static void scaleup(uint8_t *dst, const uint8_t *src, int w) +{ + int x; + for (x = 0; x < w - 7; x+=8) { + dst[x + 0] = + dst[x + 1] = src[(x>>1) + 0]; + dst[x + 2] = + dst[x + 3] = src[(x>>1) + 1]; + dst[x + 4] = + dst[x + 5] = src[(x>>1) + 2]; + dst[x + 6] = + dst[x + 7] = src[(x>>1) + 3]; + } + for (; x < w; x++) { + dst[x] = src[(x>>1)]; + } +} + +static void scaleup_rev(uint8_t *dst, const uint8_t *src, int w) +{ + int x; + + for (x = w - 1; (x+1) & 7; x--) { + dst[x] = src[(x>>1)]; + } + for (x -= 7; x >= 0; x -= 8) { + dst[x + 6] = + dst[x + 7] = src[(x>>1) + 3]; + dst[x + 4] = + dst[x + 5] = src[(x>>1) + 2]; + dst[x + 2] = + dst[x + 3] = src[(x>>1) + 1]; + dst[x + 0] = + dst[x + 1] = src[(x>>1) + 0]; + } +} + +static void scaledown(uint8_t *dst, const uint8_t *src, int w) +{ + int x; + for (x = 0; x < w - 7; x+=8) { + dst[x + 0] = src[2*x + 0]; + dst[x + 1] = src[2*x + 2]; + dst[x + 2] = src[2*x + 4]; + dst[x + 3] = src[2*x + 6]; + dst[x + 4] = src[2*x + 8]; + dst[x + 5] = src[2*x +10]; + dst[x + 6] = src[2*x +12]; + dst[x + 7] = src[2*x +14]; + } + for (; x < w; x++) { + dst[x] = src[2*x]; + } +} + static void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, int scale_h) { - int j, y, x; + int j, y; if ((gdv->scale_v == scale_v) && (gdv->scale_h == scale_h)) { return; @@ -86,14 +141,7 @@ static void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, in uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w; uint8_t *src1 = dst + PREAMBLE_SIZE + (y>>!!gdv->scale_h) * (w>>1); - for (x = w - 1; x >= 0 && !(x&1); x--) { - dst1[x] = src1[(x>>1)]; - } - - for (x--; x >= 0; x-=2) { - dst1[x ] = - dst1[x+1] = src1[(x>>1)]; - } + scaleup_rev(dst1, src1, w); } } else if (gdv->scale_h) { for (j = 0; j < h; j++) { @@ -108,9 +156,7 @@ static void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, in for (y = 0; y < (h>>1); y++) { uint8_t *dst1 = dst + PREAMBLE_SIZE + y * (w>>1); uint8_t *src1 = dst + PREAMBLE_SIZE + y*2 * w; - for (x = 0; x < (w>>1); x++) { - dst1[x] = src1[x*2]; - } + scaledown(dst1, src1, w>>1); } } else if (scale_h) { for (y = 0; y < (h>>1); y++) { @@ -121,9 +167,7 @@ static void rescale(GDVContext *gdv, uint8_t *dst, int w, int h, int scale_v, in } else if (scale_v) { for (y = 0; y < h; y++) { uint8_t *dst1 = dst + PREAMBLE_SIZE + y * w; - for (x = 0; x < (w>>1); x++) { - dst1[x] = dst1[x*2]; - } + scaledown(dst1, dst1, w>>1); } } @@ -481,19 +525,16 @@ static int gdv_decode_frame(AVCodecContext *avctx, void *data, } } else { int sidx = PREAMBLE_SIZE, didx = 0; - int y, x; + int y; for (y = 0; y < avctx->height; y++) { if (!gdv->scale_v) { memcpy(dst + didx, gdv->frame + sidx, avctx->width); } else { - for (x = 0; x < avctx->width - 1; x+=2) { - dst[didx + x ] = - dst[didx + x + 1] = gdv->frame[sidx + (x>>1)]; - } - for (; x < avctx->width; x++) { - dst[didx + x] = gdv->frame[sidx + (x>>1)]; - } + uint8_t *dst2 = dst + didx; + uint8_t *src2 = gdv->frame + sidx; + + scaleup(dst2, src2, avctx->width); } if (!gdv->scale_h || ((y & 1) == 1)) { sidx += !gdv->scale_v ? avctx->width : avctx->width/2; From 3a52cae2c70a8409c96f4df63dff85dd5460d8bc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 4 Jan 2019 02:46:29 +0100 Subject: [PATCH 081/153] avcodec/tests/rangecoder: initialize array to avoid valgrind warning Found-by: jamrial Signed-off-by: Michael Niedermayer (cherry picked from commit c15972f0af7679b466dd4a10a54ab2f04f9372c8) Signed-off-by: Michael Niedermayer --- libavcodec/tests/rangecoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/tests/rangecoder.c b/libavcodec/tests/rangecoder.c index 2da5c0ce33ade..3a8ba6759cb33 100644 --- a/libavcodec/tests/rangecoder.c +++ b/libavcodec/tests/rangecoder.c @@ -29,7 +29,7 @@ int main(void) { RangeCoder c; - uint8_t b[9 * SIZE]; + uint8_t b[9 * SIZE] = {0}; uint8_t r[9 * SIZE]; int i; uint8_t state[10]; From 29d978c91e8e675e025552eeab16a38c051cb3f1 Mon Sep 17 00:00:00 2001 From: James Almer Date: Tue, 1 Jan 2019 15:26:31 -0300 Subject: [PATCH 082/153] configure: bump year Happy new year! (cherry picked from commit 3209d7b3930bab554bf7d97d8041d9d0b88423a8) Signed-off-by: Michael Niedermayer --- configure | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure b/configure index a70c5f9e9e397..7310b962f2d55 100755 --- a/configure +++ b/configure @@ -7243,7 +7243,7 @@ cat > $TMPH < Date: Thu, 17 Jan 2019 22:35:10 +0100 Subject: [PATCH 083/153] avutil/mem: Optimize fill32() by unrolling and using 64bit Reviewed-by: Marton Balint Signed-off-by: Michael Niedermayer (cherry picked from commit 12b1338be376a3e5fb606d9fe41b58dc4a9e62c7) Signed-off-by: Michael Niedermayer --- libavutil/mem.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/libavutil/mem.c b/libavutil/mem.c index 6149755a6b88e..88fe09b1794aa 100644 --- a/libavutil/mem.c +++ b/libavutil/mem.c @@ -399,6 +399,18 @@ static void fill32(uint8_t *dst, int len) { uint32_t v = AV_RN32(dst - 4); +#if HAVE_FAST_64BIT + uint64_t v2= v + ((uint64_t)v<<32); + while (len >= 32) { + AV_WN64(dst , v2); + AV_WN64(dst+ 8, v2); + AV_WN64(dst+16, v2); + AV_WN64(dst+24, v2); + dst += 32; + len -= 32; + } +#endif + while (len >= 4) { AV_WN32(dst, v); dst += 4; From a8b5990f4594d511a854f7d9920573d33c85253a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 25 Dec 2018 23:15:20 +0100 Subject: [PATCH 084/153] avutil/imgutils: Optimize memset_bytes() by using av_memcpy_backptr() This is strongly based on code by Marton Balint, and depends on the previous commit Fixes: Timeout Fixes: 11502/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WCMV_fuzzer-5664893810769920 Before: Executed clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WCMV_fuzzer-5664893810769920 in 11209 ms After: Executed clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WCMV_fuzzer-5664893810769920 in 4104 ms Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Marton Balint Signed-off-by: Michael Niedermayer (cherry picked from commit f64c0dffa13e6263de3fdff0058ab2fdb03ac1d6) Signed-off-by: Michael Niedermayer --- libavutil/imgutils.c | 27 +++++---------------------- 1 file changed, 5 insertions(+), 22 deletions(-) diff --git a/libavutil/imgutils.c b/libavutil/imgutils.c index 4938a7ef6767f..afc73e2def167 100644 --- a/libavutil/imgutils.c +++ b/libavutil/imgutils.c @@ -501,7 +501,6 @@ int av_image_copy_to_buffer(uint8_t *dst, int dst_size, static void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear, size_t clear_size) { - size_t pos = 0; int same = 1; int i; @@ -521,28 +520,12 @@ static void memset_bytes(uint8_t *dst, size_t dst_size, uint8_t *clear, if (clear_size == 1) { memset(dst, clear[0], dst_size); dst_size = 0; - } else if (clear_size == 2) { - uint16_t val = AV_RN16(clear); - for (; dst_size >= 2; dst_size -= 2) { - AV_WN16(dst, val); - dst += 2; - } - } else if (clear_size == 4) { - uint32_t val = AV_RN32(clear); - for (; dst_size >= 4; dst_size -= 4) { - AV_WN32(dst, val); - dst += 4; - } - } else if (clear_size == 8) { - uint32_t val = AV_RN64(clear); - for (; dst_size >= 8; dst_size -= 8) { - AV_WN64(dst, val); - dst += 8; - } + } else { + if (clear_size > dst_size) + clear_size = dst_size; + memcpy(dst, clear, clear_size); + av_memcpy_backptr(dst + clear_size, clear_size, dst_size - clear_size); } - - for (; dst_size; dst_size--) - *dst++ = clear[pos++ % clear_size]; } // Maximum size in bytes of a plane element (usually a pixel, or multiple pixels From 552733d48ba591eb8d6821da428ee2ef42429e49 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 12 Jan 2019 19:37:18 +0100 Subject: [PATCH 085/153] avcodec/tiff: Check for 12bit gray fax Fixes: Assertion failure Fixes: 11898/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TIFF_fuzzer-5759794191794176 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit ec28a85107cccece4dce17c0ccb633defe2d6e98) Signed-off-by: Michael Niedermayer --- libavcodec/tiff.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/tiff.c b/libavcodec/tiff.c index d5b88923fd575..bf17d9fe60f4e 100644 --- a/libavcodec/tiff.c +++ b/libavcodec/tiff.c @@ -571,7 +571,7 @@ static int tiff_unpack_strip(TiffContext *s, AVFrame *p, uint8_t *dst, int strid if (s->compr == TIFF_CCITT_RLE || s->compr == TIFF_G3 || s->compr == TIFF_G4) { - if (is_yuv) + if (is_yuv || p->format == AV_PIX_FMT_GRAY12) return AVERROR_INVALIDDATA; return tiff_unpack_fax(s, dst, stride, src, size, width, lines); From 31fa50f3d97ca4c722e2b35af7b66a4b44a8f46a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 12 Jan 2019 22:36:00 +0100 Subject: [PATCH 086/153] avcodec/prosumer: Error out if decompress() stops reading data if 0 is encountered in the LUT then decompress() will continue to output 0 bytes but never read more data. Without a specification it is impossible to say if this is invalid or a feature. None of the valid prosumer files tested cause a 0 to be read, so it is likely not a intended feature. Fixes: Timeout Fixes: 11266/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PROSUMER_fuzzer-5681827423977472 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 62f8d27ef1995354d6529ea0d9428501d7f914b4) Signed-off-by: Michael Niedermayer --- libavcodec/prosumer.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/libavcodec/prosumer.c b/libavcodec/prosumer.c index 505de71980103..93f0c84d3a9b5 100644 --- a/libavcodec/prosumer.c +++ b/libavcodec/prosumer.c @@ -99,6 +99,8 @@ static int decompress(GetByteContext *gb, int size, PutByteContext *pb, const ui } idx = a >> 20; b = lut[2 * idx]; + if (!b) + return AVERROR_INVALIDDATA; continue; } idx = 2; @@ -159,8 +161,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, memset(s->decbuffer, 0, s->size); bytestream2_init(&s->gb, avpkt->data, avpkt->size); bytestream2_init_writer(&s->pb, s->decbuffer, s->size); - - decompress(&s->gb, AV_RL32(avpkt->data + 28) >> 1, &s->pb, s->lut); + ret = decompress(&s->gb, AV_RL32(avpkt->data + 28) >> 1, &s->pb, s->lut); + if (ret < 0) + return ret; vertical_predict((uint32_t *)s->decbuffer, 0, (uint32_t *)s->initial_line, s->stride, 1); vertical_predict((uint32_t *)s->decbuffer, s->stride, (uint32_t *)s->decbuffer, s->stride, avctx->height - 1); From bcfd82b0be0a389497d641b330e29923ce05e5fe Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 21 Jan 2019 08:34:57 +0100 Subject: [PATCH 087/153] Update for 4.1.1 Signed-off-by: Michael Niedermayer --- Changelog | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ RELEASE | 2 +- doc/Doxyfile | 2 +- 3 files changed, 68 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 97ea8e12c3107..0919015174afb 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,72 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. +version 4.1.1: +- avcodec/prosumer: Error out if decompress() stops reading data +- avcodec/tiff: Check for 12bit gray fax +- avutil/imgutils: Optimize memset_bytes() by using av_memcpy_backptr() +- avutil/mem: Optimize fill32() by unrolling and using 64bit +- configure: bump year +- avcodec/tests/rangecoder: initialize array to avoid valgrind warning +- avcodec/gdv: Optimize and factorize scaling loops +- avcodec/h264_slice: Fix integer overflow in implicit_weight_table() +- avcodec/exr: set layer_match in all branches +- avcodec/exr: Check for duplicate channel index +- avfilter/vf_tonemap_opencl: Make static tables const +- doc/indevs: fix upto typo +- avcodec/4xm: Fix returned error codes +- avformat/libopenmpt: Fix successfull typo +- avcodec/v4l2_m2m: fix cant typo +- avcodec/mjpegbdec: Fix some misplaced {} and spaces +- avformat/wvdec: detect and error out on WavPack DSD files +- avcodec/mips: Fix failed case: hevc-conformance-AMP_A_Samsung_* when enable msa +- avcodec/fic: Fail on invalid slice size/off +- avcodec/ilbcdec: fix integer overflow in energy +- postproc/postprocess_template: remove FF_REG_sp from clobber list +- postproc/postprocess_template: Avoid using %4 for the threshold compare +- libavformat/mov: Fix NULL-dereference read for some encrypted content. +- avcodec/rpza: Check that there is enough data for all the blocks +- avcodec/rpza: Move frame allocation to a later point +- avcodec/avcodec: Document the data type for AV_PKT_DATA_MPEGTS_STREAM_ID +- avformat/mpegts: Fix side data type for stream id +- tests/fate/filter-video: increase fuzz for fate-filter-refcmp-psnr-rgb +- avcodec/mjpegdec: Fix indention of ljpeg_decode_yuv_scan() +- lavf/id3v2: fail read_apic on EOF reading mimetype +- avcodec/rasc: Check that the number of moves is less than or equal the number of pixels +- avformat/nutenc: Document trailer index assert better +- lavf/mov: ensure only one tkhd per trak +- avcodec/clearvideo: Check remaining input bits in P macro block loop +- avcodec/rasc: Check input space before reading chunk +- avcodec/dxv: Check that there is enough data to decompress +- avcodec/ppc/hevcdsp: Fix build failures with powerpc-linux-gnu-gcc-4.8 with --disable-optimizations +- avcodec/msvideo1: Check for too small dimensions +- avcodec/wmv2dec: Skip I frame if its smaller than 1/8 of the minimal size +- avcodec/msmpeg4dec: Skip frame if its smaller than 1/8 of the minimal size +- avcodec/truemotion2rt: Fix rounding in input size check +- avcodec/diracdec: Check component quant +- avcodec/tiff: Limit filtering to decoded data +- avcodec/truemotion2: fix integer overflows in tm2_low_chroma() +- avcodec/pngdec: Check compression method +- fftools/ffmpeg: Repair reinit_filter feature +- avcodec/shorten: Fix integer overflow with offset +- avcodec/imm4: Use ff_set_dimensions() +- h264_redundant_pps: Fix logging context +- avfilter/af_asetnsamples: fix last frame props +- cbs_av1: Fix reading of overlong uvlc codes +- avcodec/cbs_av1: fix parsing delta_frame_id_minus1 +- avfilter/vf_overlay: fix filtering with negative y +- avformat/movenc: get number of written bytes from bitstream writer +- avformat/movenc: fix size calculation in mov_write_eac3_tag() +- avfilter/vf_overlay: fix crash with negative y +- avcodec/mpeg_er: fix clearing chroma blocks for 422 and 444 +- avfilter/af_afade: fix duration maximum +- avfilter/vf_fade: fix start/duration max value +- avcodec/cbs_av1: fix parsing signed integer values +- avcodec/cbs_av1: fix storage size for segmentation_params feature_value fields +- configure: Add missing xlib dependency for VAAPI X11 code +- avcodec/hevcdec: fix non-ref frame judgement + + version 4.1: - deblock filter - tmix filter diff --git a/RELEASE b/RELEASE index 7d5c902e77790..627a3f43a64f9 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -4.1 +4.1.1 diff --git a/doc/Doxyfile b/doc/Doxyfile index 452057c46b11d..3fcdbd74d1537 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.1 +PROJECT_NUMBER = 4.1.1 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From 62f5325ca30a3cc27c625bb468d65e2e4bfd7996 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 15 Jan 2019 00:02:25 +0100 Subject: [PATCH 088/153] avcodec/ilbcdec: Fix integer overflow in construct_vector() webrtc contains explicit code to ignore the undefined behavior (RTC_NO_SANITIZE / OverflowingAddS32S32ToS32()) Probably fixes: Integer overflow (unreproducable here) Probably fixes: 12215/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ILBC_fuzzer-5767142427852800 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit c95d0fb23917c35886f3b62daa05af20d2700a1e) Signed-off-by: Michael Niedermayer --- libavcodec/ilbcdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/ilbcdec.c b/libavcodec/ilbcdec.c index 50012c02317ca..643547f4ab969 100644 --- a/libavcodec/ilbcdec.c +++ b/libavcodec/ilbcdec.c @@ -745,7 +745,7 @@ static void construct_vector ( for (j = 0; j < veclen; j++) { a32 = SPL_MUL_16_16(*gainPtr++, cbvec0[j]); a32 += SPL_MUL_16_16(*gainPtr++, cbvec1[j]); - a32 += SPL_MUL_16_16(*gainPtr, cbvec2[j]); + a32 += (unsigned)SPL_MUL_16_16(*gainPtr, cbvec2[j]); gainPtr -= 2; decvector[j] = (a32 + 8192) >> 14; } From d8b8b27dc3126c9c18d22b81815076c43ebcac7f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 15 Jan 2019 00:09:30 +0100 Subject: [PATCH 089/153] avcodec/ilbcdec: Fix undefined integer overflow lsf2poly() The addition is moved up into the context where the variable is unsigned avoiding the undefined behavior Fixes: runtime error: signed integer overflow: 2147481972 + 4096 cannot be represented in type 'int' Fixes: 12444/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ILBC_fuzzer-5755706244857856 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 4523cc5e75c8ecfba8975d16e96c29f9bf70973f) Signed-off-by: Michael Niedermayer --- libavcodec/ilbcdec.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libavcodec/ilbcdec.c b/libavcodec/ilbcdec.c index 643547f4ab969..bba83a589630f 100644 --- a/libavcodec/ilbcdec.c +++ b/libavcodec/ilbcdec.c @@ -408,11 +408,11 @@ static void lsf2poly(int16_t *a, int16_t *lsf) a[0] = 4096; for (i = 5; i > 0; i--) { - tmp = f[0][6 - i] + (unsigned)f[1][6 - i]; - a[6 - i] = (tmp + 4096) >> 13; + tmp = f[0][6 - i] + (unsigned)f[1][6 - i] + 4096; + a[6 - i] = tmp >> 13; - tmp = f[0][6 - i] - (unsigned)f[1][6 - i]; - a[5 + i] = (tmp + 4096) >> 13; + tmp = f[0][6 - i] - (unsigned)f[1][6 - i] + 4096; + a[5 + i] = tmp >> 13; } } From f5c9753bfdab20ad54fbdbbe85b52c82d0bb3c4b Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 23 Jan 2019 00:30:53 +0100 Subject: [PATCH 090/153] avcodec/fic: Check that there is input left in fic_decode_block() Fixes: Timeout Fixes: 12450/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_FIC_fuzzer-5661984622641152 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit db1c4acd02af4de5dfbea6012c296470679aa7a6) Signed-off-by: Michael Niedermayer --- libavcodec/fic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/fic.c b/libavcodec/fic.c index 3e363463589cd..418dff1934d14 100644 --- a/libavcodec/fic.c +++ b/libavcodec/fic.c @@ -139,6 +139,9 @@ static int fic_decode_block(FICContext *ctx, GetBitContext *gb, { int i, num_coeff; + if (get_bits_left(gb) < 8) + return AVERROR_INVALIDDATA; + /* Is it a skip block? */ if (get_bits1(gb)) { *is_p = 1; From 0f1332309aff3924fcd740cf36c61f1f9e6f026e Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 23 Jan 2019 00:16:02 +0100 Subject: [PATCH 091/153] avcodec/rasc: Check uncompressed dlta size We assume that if the compressed size is bigger than if each byte is encoded in a single raw packet that the data is invalid. Fixes: Out of memory Fixes: 12208/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RASC_fuzzer-5648916473708544 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit f4079d5174c20eddbc99eef6ebe98d411f8014c5) Signed-off-by: Michael Niedermayer --- libavcodec/rasc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/rasc.c b/libavcodec/rasc.c index 1b607ac31ea65..6e32c1540e55a 100644 --- a/libavcodec/rasc.c +++ b/libavcodec/rasc.c @@ -353,6 +353,8 @@ static int decode_dlta(AVCodecContext *avctx, compression = bytestream2_get_le32(gb); if (compression == 1) { + if (w * h * s->bpp * 3 < uncompressed_size) + return AVERROR_INVALIDDATA; ret = decode_zlib(avctx, avpkt, size, uncompressed_size); if (ret < 0) return ret; From b482e94e59b15efde07326619c3cdab5826d1320 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 23 Jan 2019 00:19:14 +0100 Subject: [PATCH 092/153] avcodec/rasc: Move ff_get_buffer() after frame checks If the frame1/2 checks fail this avoids doing the allocation of a new frame Signed-off-by: Michael Niedermayer (cherry picked from commit 9f4af97aff899571663342fbe68df8caee30097f) Signed-off-by: Michael Niedermayer --- libavcodec/rasc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/rasc.c b/libavcodec/rasc.c index 6e32c1540e55a..21fc43f325c76 100644 --- a/libavcodec/rasc.c +++ b/libavcodec/rasc.c @@ -723,12 +723,12 @@ static int decode_frame(AVCodecContext *avctx, return ret; } - if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) - return ret; - if (!s->frame2->data[0] || !s->frame1->data[0]) return AVERROR_INVALIDDATA; + if ((ret = ff_get_buffer(avctx, s->frame, 0)) < 0) + return ret; + copy_plane(avctx, s->frame2, s->frame); if (avctx->pix_fmt == AV_PIX_FMT_PAL8) memcpy(s->frame->data[1], s->frame2->data[1], 1024); From e75a73d6294807a8d4d6022280cd6e25dac32990 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 28 Jan 2019 00:53:22 +0100 Subject: [PATCH 093/153] avformat/rtsp: Clear reply in every iteration in ff_rtsp_connect() Fixes: Infinite loop Found-by: Michael Hanselmann Reviewed-by: Michael Hanselmann Signed-off-by: Michael Niedermayer (cherry picked from commit 0b50f27635f684ec0526e9975c9979f35bbf486b) Signed-off-by: Michael Niedermayer --- libavformat/rtsp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index ceb770a3a4901..82c6c12af572c 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -1663,7 +1663,7 @@ int ff_rtsp_connect(AVFormatContext *s) char tcpname[1024], cmd[2048], auth[128]; const char *lower_rtsp_proto = "tcp"; int port, err, tcp_fd; - RTSPMessageHeader reply1 = {0}, *reply = &reply1; + RTSPMessageHeader reply1, *reply = &reply1; int lower_transport_mask = 0; int default_port = RTSP_DEFAULT_PORT; char real_challenge[64] = ""; @@ -1692,6 +1692,7 @@ int ff_rtsp_connect(AVFormatContext *s) rt->lower_transport_mask &= (1 << RTSP_LOWER_TRANSPORT_NB) - 1; redirect: + memset(&reply1, 0, sizeof(reply1)); /* extract hostname and port */ av_url_split(proto, sizeof(proto), auth, sizeof(auth), host, sizeof(host), &port, path, sizeof(path), s->url); From 953f97979fc292abb3fd166c90bf8fbbf8ef5a73 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 25 Jan 2019 21:30:04 +0100 Subject: [PATCH 094/153] avformat/rtsp: Check number of streams in sdp_parse_line() Fixes: OOM Found-by: Michael Hanselmann Reviewed-by: Michael Hanselmann Signed-off-by: Michael Niedermayer (cherry picked from commit 497c9b0cce559d43607bbbd679fe42f1d7e9040e) Signed-off-by: Michael Niedermayer --- libavformat/rtsp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavformat/rtsp.c b/libavformat/rtsp.c index 82c6c12af572c..975637cf54c0c 100644 --- a/libavformat/rtsp.c +++ b/libavformat/rtsp.c @@ -454,7 +454,10 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, } else if (!strcmp(st_type, "text")) { codec_type = AVMEDIA_TYPE_SUBTITLE; } - if (codec_type == AVMEDIA_TYPE_UNKNOWN || !(rt->media_type_mask & (1 << codec_type))) { + if (codec_type == AVMEDIA_TYPE_UNKNOWN || + !(rt->media_type_mask & (1 << codec_type)) || + rt->nb_rtsp_streams >= s->max_streams + ) { s1->skip_media = 1; return; } From 7816497ba081003287557096eea830327281f15d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 29 Jan 2019 01:06:01 +0100 Subject: [PATCH 095/153] avcodec/pgssubdec: Check for duplicate display segments In such a duplication the previous gets overwritten and leaks Fixes: memleak Fixes: 12510/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_PGSSUB_fuzzer-5694439226343424 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit e35c3d887b3e374c6a091342206a42da48785d70) Signed-off-by: Michael Niedermayer --- libavcodec/pgssubdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/pgssubdec.c b/libavcodec/pgssubdec.c index b897d72aab351..8c10f6d573313 100644 --- a/libavcodec/pgssubdec.c +++ b/libavcodec/pgssubdec.c @@ -676,6 +676,11 @@ static int decode(AVCodecContext *avctx, void *data, int *data_size, */ break; case DISPLAY_SEGMENT: + if (*data_size) { + av_log(avctx, AV_LOG_ERROR, "Duplicate display segment\n"); + ret = AVERROR_INVALIDDATA; + break; + } ret = display_end_segment(avctx, data, buf, segment_length); if (ret >= 0) *data_size = ret; From 31a1d2aa83096c3a07bd2f943bb9be6bda411147 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 4 Feb 2019 00:51:42 +0100 Subject: [PATCH 096/153] Changelog: update Signed-off-by: Michael Niedermayer --- Changelog | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Changelog b/Changelog index 0919015174afb..acf01244ec801 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,14 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. version 4.1.1: +- avcodec/pgssubdec: Check for duplicate display segments +- avformat/rtsp: Check number of streams in sdp_parse_line() +- avformat/rtsp: Clear reply in every iteration in ff_rtsp_connect() +- avcodec/rasc: Move ff_get_buffer() after frame checks +- avcodec/rasc: Check uncompressed dlta size +- avcodec/fic: Check that there is input left in fic_decode_block() +- avcodec/ilbcdec: Fix undefined integer overflow lsf2poly() +- avcodec/ilbcdec: Fix integer overflow in construct_vector() - avcodec/prosumer: Error out if decompress() stops reading data - avcodec/tiff: Check for 12bit gray fax - avutil/imgutils: Optimize memset_bytes() by using av_memcpy_backptr() From bcc71f30adc9de8b02f0b54636f02f20f71ef065 Mon Sep 17 00:00:00 2001 From: chcunningham Date: Wed, 6 Feb 2019 16:12:51 -0800 Subject: [PATCH 097/153] avformat/mov.c: require tfhd to begin parsing trun Detecting missing tfhd avoids re-using tfhd track info from the previous moof. For files with multiple tracks, this may make a mess of the avindex and fragindex, which can later trigger av_assert0 in mov_read_trun(). Reviewed-by: Derek Buitenhuis Signed-off-by: Michael Niedermayer (cherry picked from commit 3ea87e5d9ea075d5b3c0f4f8c6c48e514b454cbe) Signed-off-by: Michael Niedermayer --- libavformat/isom.h | 1 + libavformat/mov.c | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/libavformat/isom.h b/libavformat/isom.h index e629663949659..69452cae8e58f 100644 --- a/libavformat/isom.h +++ b/libavformat/isom.h @@ -87,6 +87,7 @@ typedef struct MOVAtom { struct MOVParseTableEntry; typedef struct MOVFragment { + int found_tfhd; unsigned track_id; uint64_t base_data_offset; uint64_t moof_offset; diff --git a/libavformat/mov.c b/libavformat/mov.c index ff7fdd48e2756..4b67044219715 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1370,6 +1370,9 @@ static void fix_frag_index_entries(MOVFragmentIndex *frag_index, int index, static int mov_read_moof(MOVContext *c, AVIOContext *pb, MOVAtom atom) { + // Set by mov_read_tfhd(). mov_read_trun() will reject files missing tfhd. + c->fragment.found_tfhd = 0; + if (!c->has_looked_for_mfra && c->use_mfra_for > 0) { c->has_looked_for_mfra = 1; if (pb->seekable & AVIO_SEEKABLE_NORMAL) { @@ -4549,6 +4552,8 @@ static int mov_read_tfhd(MOVContext *c, AVIOContext *pb, MOVAtom atom) MOVTrackExt *trex = NULL; int flags, track_id, i; + c->fragment.found_tfhd = 1; + avio_r8(pb); /* version */ flags = avio_rb24(pb); @@ -4684,6 +4689,11 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) AVIndexEntry *new_entries; MOVFragmentStreamInfo * frag_stream_info; + if (!frag->found_tfhd) { + av_log(c->fc, AV_LOG_ERROR, "trun track id unknown, no tfhd was found\n"); + return AVERROR_INVALIDDATA; + } + for (i = 0; i < c->fc->nb_streams; i++) { if (c->fc->streams[i]->id == frag->track_id) { st = c->fc->streams[i]; From 00cdf4e4e51750daa1e99ecbd49d6ee5f98dac51 Mon Sep 17 00:00:00 2001 From: chcunningham Date: Thu, 7 Feb 2019 14:58:17 -0800 Subject: [PATCH 098/153] avformat/mov: validate chunk_count vs stsc_data Bad content may contain stsc boxes with a first_chunk index that exceeds stco.entries (chunk_count). This ammends the existing check to include cases where chunk_count == 0. It also patches up the case when stsc refers to unknown chunks, but stts has no samples (so we can simply ignore stsc). Signed-off-by: Michael Niedermayer (cherry picked from commit 1c15449ca9a5bfa387868ac55628397273da761f) Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 4b67044219715..38c1d9b7eb3a2 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -2696,8 +2696,11 @@ static inline int64_t mov_get_stsc_samples(MOVStreamContext *sc, unsigned int in if (mov_stsc_index_valid(index, sc->stsc_count)) chunk_count = sc->stsc_data[index + 1].first - sc->stsc_data[index].first; - else + else { + // Validation for stsc / stco happens earlier in mov_read_stsc + mov_read_trak. + av_assert0(sc->stsc_data[index].first <= sc->chunk_count); chunk_count = sc->chunk_count - (sc->stsc_data[index].first - 1); + } return sc->stsc_data[index].count * (int64_t)chunk_count; } @@ -4175,6 +4178,13 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) c->trak_index = -1; + // Here stsc refers to a chunk not described in stco. This is technically invalid, + // but we can overlook it (clearing stsc) whenever stts_count == 0 (indicating no samples). + if (!sc->chunk_count && !sc->stts_count && sc->stsc_count) { + sc->stsc_count = 0; + av_freep(&sc->stsc_data); + } + /* sanity checks */ if ((sc->chunk_count && (!sc->stts_count || !sc->stsc_count || (!sc->sample_size && !sc->sample_count))) || @@ -4183,7 +4193,7 @@ static int mov_read_trak(MOVContext *c, AVIOContext *pb, MOVAtom atom) st->index); return 0; } - if (sc->chunk_count && sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) { + if (sc->stsc_count && sc->stsc_data[ sc->stsc_count - 1 ].first > sc->chunk_count) { av_log(c->fc, AV_LOG_ERROR, "stream %d, contradictionary STSC and STCO\n", st->index); return AVERROR_INVALIDDATA; From 74700e50bf7444930bfc12935bd3e17cd5f766c1 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 9 Feb 2019 18:20:02 +0100 Subject: [PATCH 099/153] Changelog: update Signed-off-by: Michael Niedermayer --- Changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog b/Changelog index acf01244ec801..809d2967a2ca4 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,8 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. version 4.1.1: +- avformat/mov: validate chunk_count vs stsc_data +- avformat/mov: require tfhd to begin parsing trun - avcodec/pgssubdec: Check for duplicate display segments - avformat/rtsp: Check number of streams in sdp_parse_line() - avformat/rtsp: Clear reply in every iteration in ff_rtsp_connect() From 33c8009773500fe969af9044a81ca6b18a17a83d Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 10 Feb 2019 17:41:38 -0300 Subject: [PATCH 100/153] avcodec/cbs_av1: don't call cbs_av1_read_trailing_bits() when no bits remain in the OBU Reviewed-by: jkqxz Signed-off-by: James Almer (cherry picked from commit 3e8b8b6b509c8c37defd3a8c32883fa54bc00de8) --- libavcodec/cbs_av1.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index 535139e7038f5..4513287ef96e1 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -1071,8 +1071,12 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, if (obu->obu_size > 0 && obu->header.obu_type != AV1_OBU_TILE_GROUP && obu->header.obu_type != AV1_OBU_FRAME) { - err = cbs_av1_read_trailing_bits(ctx, &gbc, - obu->obu_size * 8 + start_pos - end_pos); + int nb_bits = obu->obu_size * 8 + start_pos - end_pos; + + if (nb_bits <= 0) + return AVERROR_INVALIDDATA; + + err = cbs_av1_read_trailing_bits(ctx, &gbc, nb_bits); if (err < 0) return err; } From 110eff79caf41a1c0ba9f35f5d46d91f8097be5f Mon Sep 17 00:00:00 2001 From: Marton Balint Date: Sun, 27 Jan 2019 19:48:12 +0100 Subject: [PATCH 101/153] avformat/async: fix assertion condition when draining buffer Fixes some random assertion failures with ffprobe -show_packets async:samples/ffmpeg-bugs/trac/ticket6132/Samsung_HDR_-_Chasing_the_Light.ts > /dev/null Signed-off-by: Marton Balint (cherry picked from commit 4b46d1ee463f6bb2d2be967d418d275a44fe2a9c) --- libavformat/async.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/async.c b/libavformat/async.c index 54dbd2312a24c..4e295b5e10fb0 100644 --- a/libavformat/async.c +++ b/libavformat/async.c @@ -142,7 +142,7 @@ static int ring_size_of_read_back(RingBuffer *ring) static int ring_drain(RingBuffer *ring, int offset) { av_assert2(offset >= -ring_size_of_read_back(ring)); - av_assert2(offset <= -ring_size(ring)); + av_assert2(offset <= ring_size(ring)); ring->read_pos += offset; return 0; } From 53f3f5233f38aef0b544ebfbb2c450134aae0639 Mon Sep 17 00:00:00 2001 From: Charles Liu Date: Sun, 3 Feb 2019 23:09:06 +0800 Subject: [PATCH 102/153] avformat/mov: fix hang while seek on a kind of fragmented mp4 Binary searching would hang if the fragment items do NOT have timestamp for the specified stream. For example, a fmp4 consists of separated 'moof' boxes for each track, and separated 'sidx' for each segment, but no 'mfra' box. Then every fragment item only have the timestamp for one of its tracks. Example: ffmpeg -f lavfi -i testsrc -f lavfi -i sine -movflags dash+frag_keyframe+skip_trailer+separate_moof -t 1 out.mp4 ffmpeg -ss 0.5 -i out.mp4 -f null none Also fixes the hang in ticket #7572, but not the reason for having AV_NOPTS_VALUE timestamps there. Signed-off-by: Charles Liu Signed-off-by: Marton Balint (cherry picked from commit aa25198f1b925a464bdfa83a98476f08d26c9209) --- libavformat/mov.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 38c1d9b7eb3a2..3491d680db27f 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -1270,7 +1270,7 @@ static int64_t get_frag_time(MOVFragmentIndex *frag_index, static int search_frag_timestamp(MOVFragmentIndex *frag_index, AVStream *st, int64_t timestamp) { - int a, b, m; + int a, b, m, m0; int64_t frag_time; int id = -1; @@ -1286,15 +1286,18 @@ static int search_frag_timestamp(MOVFragmentIndex *frag_index, b = frag_index->nb_items; while (b - a > 1) { - m = (a + b) >> 1; - frag_time = get_frag_time(frag_index, m, id); - if (frag_time != AV_NOPTS_VALUE) { - if (frag_time >= timestamp) - b = m; - if (frag_time <= timestamp) - a = m; - } + m0 = m = (a + b) >> 1; + + while (m < b && + (frag_time = get_frag_time(frag_index, m, id)) == AV_NOPTS_VALUE) + m++; + + if (m < b && frag_time <= timestamp) + a = m; + else + b = m0; } + return a; } From 7e204f72607c95a7d7f791e085ba48882e778a9b Mon Sep 17 00:00:00 2001 From: Alex Mogurenko Date: Fri, 28 Dec 2018 22:30:08 +0200 Subject: [PATCH 103/153] avcodec/prores_ks: Fix luma quantization if q >= MAX_STORED_Q The problem occurs in slice quant estimation and slice encoding: If the slice quant is larger than MAX_STORED_Q we don't use pre-calculated quant matrices, but generate a new one, but both qmat and qmat_chroma both point to the same table, so the luma table ends up having chroma table values. Add custom_chroma_q the same way as custom_q. Signed-off-by: Derek Buitenhuis (cherry picked from commit e4788ae31b2e9af45d11f4bf4498c075dcc25a6c) Signed-off-by: Michael Niedermayer --- libavcodec/proresenc_kostya.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c index 81f3865ea6ef4..123f6c1f5a3b3 100644 --- a/libavcodec/proresenc_kostya.c +++ b/libavcodec/proresenc_kostya.c @@ -221,6 +221,7 @@ typedef struct ProresThreadData { DECLARE_ALIGNED(16, int16_t, blocks)[MAX_PLANES][64 * 4 * MAX_MBS_PER_SLICE]; DECLARE_ALIGNED(16, uint16_t, emu_buf)[16 * 16]; int16_t custom_q[64]; + int16_t custom_chroma_q[64]; struct TrellisNode *nodes; } ProresThreadData; @@ -231,6 +232,7 @@ typedef struct ProresContext { int16_t quants[MAX_STORED_Q][64]; int16_t quants_chroma[MAX_STORED_Q][64]; int16_t custom_q[64]; + int16_t custom_chroma_q[64]; const uint8_t *quant_mat; const uint8_t *quant_chroma_mat; const uint8_t *scantable; @@ -573,7 +575,7 @@ static int encode_slice(AVCodecContext *avctx, const AVFrame *pic, qmat_chroma = ctx->quants_chroma[quant]; } else { qmat = ctx->custom_q; - qmat_chroma = ctx->custom_q; + qmat_chroma = ctx->custom_chroma_q; for (i = 0; i < 64; i++) { qmat[i] = ctx->quant_mat[i] * quant; qmat_chroma[i] = ctx->quant_chroma_mat[i] * quant; @@ -901,7 +903,7 @@ static int find_slice_quant(AVCodecContext *avctx, qmat_chroma = ctx->quants_chroma[q]; } else { qmat = td->custom_q; - qmat_chroma = td->custom_q; + qmat_chroma = td->custom_chroma_q; for (i = 0; i < 64; i++) { qmat[i] = ctx->quant_mat[i] * q; qmat_chroma[i] = ctx->quant_chroma_mat[i] * q; From 1a82246caed8496aa932a668dce6139d220f68ca Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 3 Feb 2019 15:13:03 +0100 Subject: [PATCH 104/153] avcodec/sbrdsp_fixed.c: remove input value limit for sbr_sum_square_c() Fixes: 1377/clusterfuzz-testcase-minimized-5487049807233024 Fixes: assertion failure in sbr_sum_square_c() Signed-off-by: Michael Niedermayer (cherry picked from commit 4cde7e62dbaa63eda173e8d24a97d273890f282c) Signed-off-by: Michael Niedermayer --- libavcodec/sbrdsp_fixed.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/libavcodec/sbrdsp_fixed.c b/libavcodec/sbrdsp_fixed.c index 57d98da97997f..91fa664c0872e 100644 --- a/libavcodec/sbrdsp_fixed.c +++ b/libavcodec/sbrdsp_fixed.c @@ -34,32 +34,36 @@ static SoftFloat sbr_sum_square_c(int (*x)[2], int n) { SoftFloat ret; - uint64_t accu, round; + uint64_t accu = 0, round; uint64_t accu0 = 0, accu1 = 0, accu2 = 0, accu3 = 0; int i, nz, nz0; unsigned u; + nz = 0; for (i = 0; i < n; i += 2) { - // Larger values are inavlid and could cause overflows of accu. - av_assert2(FFABS(x[i + 0][0]) >> 30 == 0); accu0 += (int64_t)x[i + 0][0] * x[i + 0][0]; - av_assert2(FFABS(x[i + 0][1]) >> 30 == 0); accu1 += (int64_t)x[i + 0][1] * x[i + 0][1]; - av_assert2(FFABS(x[i + 1][0]) >> 30 == 0); accu2 += (int64_t)x[i + 1][0] * x[i + 1][0]; - av_assert2(FFABS(x[i + 1][1]) >> 30 == 0); accu3 += (int64_t)x[i + 1][1] * x[i + 1][1]; + if ((accu0|accu1|accu2|accu3) > UINT64_MAX - INT32_MIN*(int64_t)INT32_MIN || i+2>=n) { + accu0 >>= nz; + accu1 >>= nz; + accu2 >>= nz; + accu3 >>= nz; + while ((accu0|accu1|accu2|accu3) > (UINT64_MAX - accu) >> 2) { + accu0 >>= 1; + accu1 >>= 1; + accu2 >>= 1; + accu3 >>= 1; + accu >>= 1; + nz ++; + } + accu += accu0 + accu1 + accu2 + accu3; + accu0 = accu1 = accu2 = accu3 = 0; + } } - nz0 = 15; - while ((accu0|accu1|accu2|accu3) >> 62) { - accu0 >>= 1; - accu1 >>= 1; - accu2 >>= 1; - accu3 >>= 1; - nz0 --; - } - accu = accu0 + accu1 + accu2 + accu3; + nz0 = 15 - nz; u = accu >> 32; if (u) { From d25f388584a36b709c780b4bf91de2cabfe6137f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 12 Feb 2019 23:28:35 +0100 Subject: [PATCH 105/153] avformat/mov: Do not use reference stream in mov_read_sidx() if there is no reference stream Fixes: NULL pointer dereference Fixes: clusterfuzz-testcase-minimized-audio_decoder_fuzzer-5634316373721088 Reported-by: Chris Cunningham Signed-off-by: Michael Niedermayer (cherry picked from commit b0d8b7cb8e86367178ef0c35dcae359d820c3b27) Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 3491d680db27f..60309b486919d 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -5050,7 +5050,7 @@ static int mov_read_sidx(MOVContext *c, AVIOContext *pb, MOVAtom atom) } } } - for (i = 0; i < c->fc->nb_streams; i++) { + if (ref_st) for (i = 0; i < c->fc->nb_streams; i++) { st = c->fc->streams[i]; sc = st->priv_data; if (!sc->has_sidx) { From 8066cb3556e77570b72b28ccef9613ea0887d5ac Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 15 Feb 2019 01:57:09 +0100 Subject: [PATCH 106/153] avcodec/mpeg4videodec: Clear interlaced_dct for studio profile Fixes: Out of array access Fixes: 13090/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEG4_fuzzer-5408668986638336 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Kieran Kunhya Signed-off-by: Michael Niedermayer (cherry picked from commit 1f686d023b95219db933394a7704ad9aa5f01cbb) Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4videodec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index f44ee76bd4194..ecd028a87c770 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -3057,6 +3057,7 @@ static int decode_studio_vop_header(Mpeg4DecContext *ctx, GetBitContext *gb) return 0; s->partitioned_frame = 0; + s->interlaced_dct = 0; s->decode_mb = mpeg4_decode_studio_mb; decode_smpte_tc(ctx, gb); From 4d1fcd734e877b0bcb635664dbc7a0a0ff0627ec Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 6 Feb 2019 15:29:38 +0100 Subject: [PATCH 107/153] avformat/matroskadec: Do not leak queued packets on sync errors Fixes: memleak Fixes: clusterfuzz-testcase-minimized-audio_decoder_fuzzer-5649187601121280 Reported-by: Chris Cunningham Tested-by: Chris Cunningham Signed-off-by: Michael Niedermayer (cherry picked from commit d1afa7284c3feba4debfebf1b9cf8ad67640e34a) Signed-off-by: Michael Niedermayer --- libavformat/matroskadec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/matroskadec.c b/libavformat/matroskadec.c index 2daa1dba6fc29..2b42cff9a8f5d 100644 --- a/libavformat/matroskadec.c +++ b/libavformat/matroskadec.c @@ -3541,7 +3541,7 @@ static int matroska_read_packet(AVFormatContext *s, AVPacket *pkt) ret = matroska_resync(matroska, pos); } - return ret; + return 0; } static int matroska_read_seek(AVFormatContext *s, int stream_index, From cc5361ed18ab0f69cfbead7afc88fb81ed4b36ae Mon Sep 17 00:00:00 2001 From: Kevin Backhouse via RT Date: Wed, 6 Feb 2019 11:29:22 +0000 Subject: [PATCH 108/153] avcodec/htmlsubtitles: Fixes denial of service due to use of sscanf in inner loop for tag scaning Fixes: [Semmle Security Reports #19438] Fixes: dos_sscanf1.mkv Signed-off-by: Michael Niedermayer (cherry picked from commit 1f00c97bc3475c477f3c468cf2d924d5761d0982) Signed-off-by: Michael Niedermayer --- libavcodec/htmlsubtitles.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/libavcodec/htmlsubtitles.c b/libavcodec/htmlsubtitles.c index fb9f90042228d..c0cfccfb16155 100644 --- a/libavcodec/htmlsubtitles.c +++ b/libavcodec/htmlsubtitles.c @@ -74,6 +74,34 @@ struct font_tag { uint32_t color; }; +/* + * Fast code for scanning the rest of a tag. Functionally equivalent to + * this sscanf call: + * + * sscanf(in, "%127[^<>]>%n", buffer, lenp) == 2 + */ +static int scantag(const char* in, char* buffer, int* lenp) { + int len; + + for (len = 0; len < 128; len++) { + const char c = *in++; + switch (c) { + case '\0': + return 0; + case '<': + return 0; + case '>': + buffer[len] = '\0'; + *lenp = len+1; + return 1; + default: + break; + } + buffer[len] = c; + } + return 0; +} + /* * The general politic of the convert is to mask unsupported tags or formatting * errors (but still alert the user/subtitles writer with an error/warning) @@ -155,7 +183,7 @@ int ff_htmlmarkup_to_ass(void *log_ctx, AVBPrint *dst, const char *in) len = 0; - if (sscanf(in+tag_close+1, "%127[^<>]>%n", buffer, &len) >= 1 && len > 0) { + if (scantag(in+tag_close+1, buffer, &len) && len > 0) { const int skip = len + tag_close; const char *tagname = buffer; while (*tagname == ' ') { From f7f3937494f6734d27fc3d0081c9c7a9a19614a8 Mon Sep 17 00:00:00 2001 From: Kevin Backhouse via RT Date: Wed, 6 Feb 2019 12:56:01 +0000 Subject: [PATCH 109/153] avcodec/htmlsubtitles: Fixes denial of service due to use of sscanf in inner loop for handling braces Fixes: [Semmle Security Reports #19439] Fixes: dos_sscanf2.mkv Signed-off-by: Michael Niedermayer (cherry picked from commit 894995c41e0795c7a44f81adc4838dedc3932e65) Signed-off-by: Michael Niedermayer --- libavcodec/htmlsubtitles.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/libavcodec/htmlsubtitles.c b/libavcodec/htmlsubtitles.c index c0cfccfb16155..d9221ba16b0fb 100644 --- a/libavcodec/htmlsubtitles.c +++ b/libavcodec/htmlsubtitles.c @@ -24,6 +24,7 @@ #include "libavutil/common.h" #include "libavutil/parseutils.h" #include "htmlsubtitles.h" +#include static int html_color_parse(void *log_ctx, const char *str) { @@ -44,14 +45,32 @@ static void rstrip_spaces_buf(AVBPrint *buf) buf->str[--buf->len] = 0; } +/* + * Fast code for scanning text enclosed in braces. Functionally + * equivalent to this sscanf call: + * + * sscanf(in, "{\\an%*1u}%n", &len) >= 0 && len > 0 + */ +static int scanbraces(const char* in) { + if (strncmp(in, "{\\an", 4) != 0) { + return 0; + } + if (!isdigit(in[4])) { + return 0; + } + if (in[5] != '}') { + return 0; + } + return 1; +} + /* skip all {\xxx} substrings except for {\an%d} and all microdvd like styles such as {Y:xxx} */ static void handle_open_brace(AVBPrint *dst, const char **inp, int *an, int *closing_brace_missing) { - int len = 0; const char *in = *inp; - *an += sscanf(in, "{\\an%*1u}%n", &len) >= 0 && len > 0; + *an += scanbraces(in); if (!*closing_brace_missing) { if ( (*an != 1 && in[1] == '\\') From 11375cd1014766c50fb6f36344096f3714569fb3 Mon Sep 17 00:00:00 2001 From: Wenxiang Qian Date: Wed, 13 Feb 2019 08:47:20 +0100 Subject: [PATCH 110/153] avformat/ftp: Fix Out-of-Bounds Access and Information Leak in ftp.c:393 Signed-off-by: Michael Niedermayer (cherry picked from commit a142ffdcaec06fcbf7d4b00dbb0e5ddfb9e3344d) Signed-off-by: Michael Niedermayer --- libavformat/ftp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/ftp.c b/libavformat/ftp.c index e0720674808dd..3adc04ee1fbbf 100644 --- a/libavformat/ftp.c +++ b/libavformat/ftp.c @@ -389,7 +389,7 @@ static int ftp_file_size(FTPContext *s) static const int size_codes[] = {213, 0}; snprintf(command, sizeof(command), "SIZE %s\r\n", s->path); - if (ftp_send_command(s, command, size_codes, &res) == 213 && res) { + if (ftp_send_command(s, command, size_codes, &res) == 213 && res && strlen(res) > 4) { s->filesize = strtoll(&res[4], NULL, 10); } else { s->filesize = -1; From ec22b46a4d34e8d01a2bb69335680c2d84fb26b9 Mon Sep 17 00:00:00 2001 From: Wenxiang Qian Date: Wed, 13 Feb 2019 08:54:08 +0100 Subject: [PATCH 111/153] avformat/http: Fix Out-of-Bounds access in process_line() Signed-off-by: Michael Niedermayer (cherry picked from commit 85f91ed760a517c0d5fcf692d40a5a9d7efa9476) Signed-off-by: Michael Niedermayer --- libavformat/http.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/http.c b/libavformat/http.c index 3a35bc7eacb8f..8cd84aa3fb5b2 100644 --- a/libavformat/http.c +++ b/libavformat/http.c @@ -915,7 +915,7 @@ static int process_line(URLContext *h, char *line, int line_count, while (av_isspace(*p)) p++; resource = p; - while (!av_isspace(*p)) + while (*p && !av_isspace(*p)) p++; *(p++) = '\0'; av_log(h, AV_LOG_TRACE, "Requested resource: %s\n", resource); From 339f40f6181849bb9ecbc8ebffd88b2006e60c8d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Wed, 13 Feb 2019 10:15:04 +0100 Subject: [PATCH 112/153] avformat/webmdashenc: Check id in adaption_sets Fixes: out of array access Found-by: Wenxiang Qian Signed-off-by: Michael Niedermayer (cherry picked from commit b687b549aa0fb115861b1343208de8c2630803bf) Signed-off-by: Michael Niedermayer --- libavformat/webmdashenc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavformat/webmdashenc.c b/libavformat/webmdashenc.c index 1280d8a763bee..26b87273048fe 100644 --- a/libavformat/webmdashenc.c +++ b/libavformat/webmdashenc.c @@ -466,6 +466,7 @@ static int parse_adaptation_sets(AVFormatContext *s) continue; else if (state == new_set && !strncmp(p, "id=", 3)) { void *mem = av_realloc(w->as, sizeof(*w->as) * (w->nb_as + 1)); + const char *comma; if (mem == NULL) return AVERROR(ENOMEM); w->as = mem; @@ -474,6 +475,11 @@ static int parse_adaptation_sets(AVFormatContext *s) w->as[w->nb_as - 1].streams = NULL; p += 3; // consume "id=" q = w->as[w->nb_as - 1].id; + comma = strchr(p, ','); + if (!comma || comma - p >= sizeof(w->as[w->nb_as - 1].id)) { + av_log(s, AV_LOG_ERROR, "'id' in 'adaptation_sets' is malformed.\n"); + return AVERROR(EINVAL); + } while (*p != ',') *q++ = *p++; *q = 0; p++; From 9495228df0288e61f9fa8ebb8ba86c14223aa949 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 14 Feb 2019 00:05:34 +0100 Subject: [PATCH 113/153] avcodec/h264_direct: Fix overflow in POC comparission Fixes: runtime error: signed integer overflow: 2147421862 - -33624063 cannot be represented in type 'int' Fixes: 12885/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_H264_fuzzer-5733516975800320 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 5ccf296e74725bc8bdfbfe500d0482daa200b6f3) Signed-off-by: Michael Niedermayer --- libavcodec/h264_direct.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavcodec/h264_direct.c b/libavcodec/h264_direct.c index ec9fca0350d4d..a01d823e7ad62 100644 --- a/libavcodec/h264_direct.c +++ b/libavcodec/h264_direct.c @@ -156,8 +156,8 @@ void ff_h264_direct_ref_list_init(const H264Context *const h, H264SliceContext * av_log(h->avctx, AV_LOG_ERROR, "co located POCs unavailable\n"); sl->col_parity = 1; } else - sl->col_parity = (FFABS(col_poc[0] - cur_poc) >= - FFABS(col_poc[1] - cur_poc)); + sl->col_parity = (FFABS(col_poc[0] - (int64_t)cur_poc) >= + FFABS(col_poc[1] - (int64_t)cur_poc)); ref1sidx = sidx = sl->col_parity; // FL -> FL & differ parity From 4e624c89fddd90907609a0cc907040204ad67468 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 21 Feb 2019 01:09:43 +0100 Subject: [PATCH 114/153] avcodec/jvdec: Check available input space before decode8x8() Fixes: Timeout (78 sec -> 15 millisec) Fixes: 13147/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_JV_fuzzer-5727107827630080 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 61523683c5a9bda9aaa7ae24764a3df0401a9877) Signed-off-by: Michael Niedermayer --- libavcodec/jvdec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/jvdec.c b/libavcodec/jvdec.c index cbe83d3c108d1..4337d5681ec94 100644 --- a/libavcodec/jvdec.c +++ b/libavcodec/jvdec.c @@ -170,6 +170,11 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, GetBitContext gb; init_get_bits(&gb, buf, 8 * video_size); + if (avctx->height/8 * (avctx->width/8) > 4 * video_size) { + av_log(avctx, AV_LOG_ERROR, "Insufficient input data for dimensions\n"); + return AVERROR_INVALIDDATA; + } + for (j = 0; j < avctx->height; j += 8) for (i = 0; i < avctx->width; i += 8) decode8x8(&gb, From ff491b15444238db26aa7c842d94eb7c1e7bc82c Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 21 Feb 2019 17:25:14 +0100 Subject: [PATCH 115/153] avcodec/zmbv: obtain frame later MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The frame is not needed that early so obtaining it later avoids the costly operation in case other checks fail. Fixes: Timeout (14sec -> 4sec) Fixes: 13140/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_ZMBV_fuzzer-5738330308739072 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Tomas Härdin Signed-off-by: Michael Niedermayer (cherry picked from commit 177b40890c6de8c6896e0a1d4a631ea1ca89c044) Signed-off-by: Michael Niedermayer --- libavcodec/zmbv.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libavcodec/zmbv.c b/libavcodec/zmbv.c index 79e0892070412..e07009d0fbdf2 100644 --- a/libavcodec/zmbv.c +++ b/libavcodec/zmbv.c @@ -525,9 +525,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac return AVERROR_INVALIDDATA; } - if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) - return ret; - if (c->comp == 0) { // uncompressed data if (c->decomp_size < len) { av_log(avctx, AV_LOG_ERROR, "Buffer too small\n"); @@ -553,6 +550,9 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, AVPac av_log(avctx, AV_LOG_ERROR, "decompressed size %d is incorrect, expected %d\n", c->decomp_len, expected_size); return AVERROR_INVALIDDATA; } + if ((ret = ff_get_buffer(avctx, frame, 0)) < 0) + return ret; + if (c->flags & ZMBV_KEYFRAME) { frame->key_frame = 1; frame->pict_type = AV_PICTURE_TYPE_I; From 92335fc02b2c86536d161db34dfbeab85bc74e75 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 23 Feb 2019 22:00:39 +0100 Subject: [PATCH 116/153] avcodec/mlpdec: Insuffient typo Signed-off-by: Michael Niedermayer (cherry picked from commit fc32e08941ea2795a3096e7a4013843e9ebf5fe3) Signed-off-by: Michael Niedermayer --- libavcodec/mlpdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/mlpdec.c b/libavcodec/mlpdec.c index 8caa266b7e723..3139a0172fa0f 100644 --- a/libavcodec/mlpdec.c +++ b/libavcodec/mlpdec.c @@ -1195,7 +1195,7 @@ static int read_access_unit(AVCodecContext *avctx, void* data, } if (length < header_size + substr_header_size) { - av_log(m->avctx, AV_LOG_ERROR, "Insuffient data for headers\n"); + av_log(m->avctx, AV_LOG_ERROR, "Insufficient data for headers\n"); goto error; } From b8dd1d2d4bde740f61ba10eea399109c5e772da9 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 19 Feb 2019 18:41:42 +0100 Subject: [PATCH 117/153] avcodec/error_resilience: Use a symmetric check for skipping MV estimation This speeds up the testcase by a factor of 4 Fixes: Timeout Fixes: 13100/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_WMV2_fuzzer-5767533905313792 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit e4289cb253e29e4d62dc46759eb1a45d8f6d82df) Signed-off-by: Michael Niedermayer --- libavcodec/error_resilience.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/error_resilience.c b/libavcodec/error_resilience.c index 1abae53f41d41..35d0c609e5ab9 100644 --- a/libavcodec/error_resilience.c +++ b/libavcodec/error_resilience.c @@ -437,7 +437,7 @@ static void guess_mv(ERContext *s) } if ((!(s->avctx->error_concealment&FF_EC_GUESS_MVS)) || - num_avail <= mb_width / 2) { + num_avail <= FFMAX(mb_width, mb_height) / 2) { for (mb_y = 0; mb_y < mb_height; mb_y++) { for (mb_x = 0; mb_x < s->mb_width; mb_x++) { const int mb_xy = mb_x + mb_y * s->mb_stride; From 662b6351c80a7768a5b46943a067b7c633e29088 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 19 Feb 2019 00:05:51 +0100 Subject: [PATCH 118/153] avcodec/jpeg2000dwt: Fix integer overflow in dwt_decode97_int() Fixes: runtime error: signed integer overflow: 2147483598 + 128 cannot be represented in type 'int' Fixes: 12926/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_JPEG2000_fuzzer-5705100733972480 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 4801eea0d465cd54670e7c19322705544e3e7524) Signed-off-by: Michael Niedermayer --- libavcodec/jpeg2000dwt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/jpeg2000dwt.c b/libavcodec/jpeg2000dwt.c index ce1678a3d74ed..badf0f8cd0586 100644 --- a/libavcodec/jpeg2000dwt.c +++ b/libavcodec/jpeg2000dwt.c @@ -531,7 +531,7 @@ static void dwt_decode97_int(DWTContext *s, int32_t *t) } for (i = 0; i < w * h; i++) - data[i] = (data[i] + ((1<>1)) >> I_PRESHIFT; + data[i] = (data[i] + ((1LL<>1)) >> I_PRESHIFT; } int ff_jpeg2000_dwt_init(DWTContext *s, int border[2][2], From 09683e1f4e215be41afa189c0dd67902a61b70fb Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 24 Feb 2019 23:39:44 +0100 Subject: [PATCH 119/153] avcodec/bethsoftvideo: Check block_type Fixes: Timeout (17 seconds -> 1 second) Fixes: 13184/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_BETHSOFTVID_fuzzer-5711446296494080 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit b8ecadec0582a1521b5d0d253376966138e6ca78) Signed-off-by: Michael Niedermayer --- libavcodec/bethsoftvideo.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libavcodec/bethsoftvideo.c b/libavcodec/bethsoftvideo.c index 274516bf4d8fa..e5a73f55a1c2a 100644 --- a/libavcodec/bethsoftvideo.c +++ b/libavcodec/bethsoftvideo.c @@ -109,6 +109,11 @@ static int bethsoftvid_decode_frame(AVCodecContext *avctx, if(yoffset >= avctx->height) return AVERROR_INVALIDDATA; dst += vid->frame->linesize[0] * yoffset; + case VIDEO_P_FRAME: + case VIDEO_I_FRAME: + break; + default: + return AVERROR_INVALIDDATA; } // main code From 29619a8ac2751508f368b24b6d83343fc030611f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 25 Feb 2019 01:26:30 +0100 Subject: [PATCH 120/153] avcodec/gdv: Check for truncated tags in decompress_5() Testcase: 13169/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_GDV_fuzzer-5666354038833152 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 5cf42f65b60d226d1223d2100cb1d90402189275) Signed-off-by: Michael Niedermayer --- libavcodec/gdv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/gdv.c b/libavcodec/gdv.c index a29de28aa144f..e946bd61dfa0a 100644 --- a/libavcodec/gdv.c +++ b/libavcodec/gdv.c @@ -294,6 +294,8 @@ static int decompress_5(AVCodecContext *avctx, unsigned skip) while (bytestream2_get_bytes_left_p(pb) > 0 && bytestream2_get_bytes_left(gb) > 0) { int tag = read_bits2(&bits, gb); + if (bytestream2_get_bytes_left(gb) < 1) + return AVERROR_INVALIDDATA; if (tag == 0) { bytestream2_put_byte(pb, bytestream2_get_byte(gb)); } else if (tag == 1) { From 6c0124d3921d95cf92adf8d052f86240d7d73a35 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 25 Feb 2019 13:26:25 +0100 Subject: [PATCH 121/153] avcodec/aic: Check remaining bits in aic_decode_coeffs() Fixes: Timeout (78 seconds -> 2 seconds) Fixes: 13186/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_AIC_fuzzer-5639516533030912 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 951bb7632fe6e3bb1a9c3b47610705871e471f34) Signed-off-by: Michael Niedermayer --- libavcodec/aic.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/aic.c b/libavcodec/aic.c index 9c6f806655e3e..dc28c83661e02 100644 --- a/libavcodec/aic.c +++ b/libavcodec/aic.c @@ -208,6 +208,9 @@ static int aic_decode_coeffs(GetBitContext *gb, int16_t *dst, int mb, idx; unsigned val; + if (get_bits_left(gb) < 5) + return AVERROR_INVALIDDATA; + has_skips = get_bits1(gb); coeff_type = get_bits1(gb); coeff_bits = get_bits(gb, 3); From c90836cc3df3ab00dad329e51cebded37d276991 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 24 Feb 2019 00:44:40 +0100 Subject: [PATCH 122/153] avcodec/qpeg: Limit copy in qpeg_decode_intra() to the available bytes Fixes: Timeout (27 sec -> 39 milli sec) Fixes: 13151/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_QPEG_fuzzer-5717536023248896 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit b819472995f55e827d6bb70dcdd86d963f65ae31) Signed-off-by: Michael Niedermayer --- libavcodec/qpeg.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/qpeg.c b/libavcodec/qpeg.c index e1210c1972060..10b55d2dff226 100644 --- a/libavcodec/qpeg.c +++ b/libavcodec/qpeg.c @@ -90,6 +90,8 @@ static void qpeg_decode_intra(QpegContext *qctx, uint8_t *dst, } } } else { + if (bytestream2_get_bytes_left(&qctx->buffer) < copy) + copy = bytestream2_get_bytes_left(&qctx->buffer); for(i = 0; i < copy; i++) { dst[filled++] = bytestream2_get_byte(&qctx->buffer); if (filled >= width) { From 67d030787e0b9b5350545bf2d2d64642d2c5ccb7 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 28 Feb 2019 00:12:14 +0100 Subject: [PATCH 123/153] avcodec/scpr: Fix use of uninitialized variable Fixes: Undefined shift Fixes: 12911/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_SCPR_fuzzer-5677102915911680 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 53248acfb3b23007c89ae822d7bcae451272d5a7) Signed-off-by: Michael Niedermayer --- libavcodec/scpr.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/scpr.c b/libavcodec/scpr.c index e41fbbec13c7b..5714e2517092a 100644 --- a/libavcodec/scpr.c +++ b/libavcodec/scpr.c @@ -512,7 +512,7 @@ static int decompress_p(AVCodecContext *avctx, { SCPRContext *s = avctx->priv_data; GetByteContext *gb = &s->gb; - int ret, temp, min, max, x, y, cx = 0, cx1 = 0; + int ret, temp = 0, min, max, x, y, cx = 0, cx1 = 0; int backstep = linesize - avctx->width; if (bytestream2_get_byte(gb) == 0) From ad12d9df1ed939e47cccc832ca4c363e68374adc Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 3 Mar 2019 00:47:47 +0100 Subject: [PATCH 124/153] avcodec/dxv: Correct integer overflow in get_opcodes() Fixes: 13099/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DXV_fuzzer-5665598896340992 Fixes: signed integer overflow: 2147483647 + 7 cannot be represented in type 'int' Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 6e0b5d3a20e107860a34e90139b860d6b8219a1d) Signed-off-by: Michael Niedermayer --- libavcodec/dxv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/dxv.c b/libavcodec/dxv.c index bf53d7d70622f..aef5ec19dd6b6 100644 --- a/libavcodec/dxv.c +++ b/libavcodec/dxv.c @@ -426,7 +426,8 @@ static int fill_optable(unsigned *table0, OpcodeTable *table1, int nb_elements) static int get_opcodes(GetByteContext *gb, uint32_t *table, uint8_t *dst, int op_size, int nb_elements) { OpcodeTable optable[1024]; - int sum, x, val, lshift, rshift, ret, size_in_bits, i, idx; + int sum, x, val, lshift, rshift, ret, i, idx; + int64_t size_in_bits; unsigned endoffset, newoffset, offset; unsigned next; uint8_t *src = (uint8_t *)gb->buffer; From 1e50a327c649c8a00741996b9f6db83fdc00285a Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 10 Mar 2019 01:40:59 +0100 Subject: [PATCH 125/153] avcodec/mpeg4videodec: Check idx in mpeg4_decode_studio_block() Fixes: Out of array access Fixes: 13500/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEG4_fuzzer-5769760178962432 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Kieran Kunhya Signed-off-by: Michael Niedermayer (cherry picked from commit d227ed5d598340e719eff7156b1aa0a4469e9a6a) Signed-off-by: Michael Niedermayer --- libavcodec/mpeg4videodec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/mpeg4videodec.c b/libavcodec/mpeg4videodec.c index ecd028a87c770..bb9f1e3f2cd69 100644 --- a/libavcodec/mpeg4videodec.c +++ b/libavcodec/mpeg4videodec.c @@ -1899,14 +1899,20 @@ static int mpeg4_decode_studio_block(MpegEncContext *s, int32_t block[64], int n code >>= 1; run = (1 << (additional_code_len - 1)) + code; idx += run; + if (idx > 63) + return AVERROR_INVALIDDATA; j = scantable[idx++]; block[j] = sign ? 1 : -1; } else if (group >= 13 && group <= 20) { /* Level value (Table B.49) */ + if (idx > 63) + return AVERROR_INVALIDDATA; j = scantable[idx++]; block[j] = get_xbits(&s->gb, additional_code_len); } else if (group == 21) { /* Escape */ + if (idx > 63) + return AVERROR_INVALIDDATA; j = scantable[idx++]; additional_code_len = s->avctx->bits_per_raw_sample + s->dct_precision + 4; flc = get_bits(&s->gb, additional_code_len); From 9bf40978c65714bd4448d6d445ffe5ac36189ec3 Mon Sep 17 00:00:00 2001 From: "Guo, Yejun" Date: Tue, 5 Mar 2019 06:09:11 +0800 Subject: [PATCH 126/153] configure: add missing pthreads extralibs dependency for libvpx-vp9 Signed-off-by: Guo, Yejun Signed-off-by: James Almer (cherry picked from commit 402bf262375dfecd0e90d7acc67c238abe952fc3) Signed-off-by: Michael Niedermayer --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 7310b962f2d55..5ba35811d1515 100755 --- a/configure +++ b/configure @@ -6162,11 +6162,11 @@ enabled libvpx && { } enabled libvpx_vp9_decoder && { check_pkg_config libvpx_vp9_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp9_dx || - check_lib libvpx_vp9_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs" + check_lib libvpx_vp9_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp9_dx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs $pthreads_extralibs" } enabled libvpx_vp9_encoder && { check_pkg_config libvpx_vp9_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp9_cx || - check_lib libvpx_vp9_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs" + check_lib libvpx_vp9_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp9_cx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs $pthreads_extralibs" } if disabled_all libvpx_vp8_decoder libvpx_vp9_decoder libvpx_vp8_encoder libvpx_vp9_encoder; then die "libvpx enabled but no supported decoders found" From 83bfd4f3b5b649fc84066495a2886bc819763fd1 Mon Sep 17 00:00:00 2001 From: "Guo, Yejun" Date: Tue, 5 Mar 2019 06:09:18 +0800 Subject: [PATCH 127/153] configure: use vpx_codec_vp8_dx/cx for libvpx-vp8 checking Signed-off-by: Guo, Yejun Signed-off-by: James Almer (cherry picked from commit d9b2668766e3e924d4ebb3c6531b449874e13666) Signed-off-by: Michael Niedermayer --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 5ba35811d1515..a9644e211bebb 100755 --- a/configure +++ b/configure @@ -6152,12 +6152,12 @@ enabled libvorbis && require_pkg_config libvorbis vorbis vorbis/codec.h enabled libvpx && { enabled libvpx_vp8_decoder && { check_pkg_config libvpx_vp8_decoder "vpx >= 1.4.0" "vpx/vpx_decoder.h vpx/vp8dx.h" vpx_codec_vp8_dx || - check_lib libvpx_vp8_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_dec_init_ver VPX_IMG_FMT_HIGHBITDEPTH" -lvpx || + check_lib libvpx_vp8_decoder "vpx/vpx_decoder.h vpx/vp8dx.h" "vpx_codec_vp8_dx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs $pthreads_extralibs" || die "ERROR: libvpx decoder version must be >=1.4.0"; } enabled libvpx_vp8_encoder && { check_pkg_config libvpx_vp8_encoder "vpx >= 1.4.0" "vpx/vpx_encoder.h vpx/vp8cx.h" vpx_codec_vp8_cx || - check_lib libvpx_vp8_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_enc_init_ver VPX_IMG_FMT_HIGHBITDEPTH" -lvpx || + check_lib libvpx_vp8_encoder "vpx/vpx_encoder.h vpx/vp8cx.h" "vpx_codec_vp8_cx VPX_IMG_FMT_HIGHBITDEPTH" "-lvpx $libm_extralibs $pthreads_extralibs" || die "ERROR: libvpx encoder version must be >=1.4.0"; } enabled libvpx_vp9_decoder && { From 5d208aac52538e67d76c3fdd173e24ada876ca47 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 5 Mar 2019 00:48:18 +0100 Subject: [PATCH 128/153] avformat/gdv: Check fps Fixes: Division by 0 Fixes: ffmpeg_zero_division.bin Found-by: Anatoly Trosinenko Signed-off-by: Michael Niedermayer (cherry picked from commit 38381400fca45d1ae6e7604335b507b7dc70a903) Signed-off-by: Michael Niedermayer --- libavformat/gdv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavformat/gdv.c b/libavformat/gdv.c index a69c349cab3c4..3ead383892fa8 100644 --- a/libavformat/gdv.c +++ b/libavformat/gdv.c @@ -86,6 +86,9 @@ static int gdv_read_header(AVFormatContext *ctx) vst->nb_frames = avio_rl16(pb); fps = avio_rl16(pb); + if (!fps) + return AVERROR_INVALIDDATA; + snd_flags = avio_rl16(pb); if (snd_flags & 1) { ast = avformat_new_stream(ctx, 0); From 04ce4cc0728e35d908da7f5e1aa71f9adf0b65de Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 5 Mar 2019 12:51:22 +0100 Subject: [PATCH 129/153] avcodec/cdgraphics: Use ff_set_dimensions() Fixes: Timeout (17 sec -> 65 milli sec) Fixes: 13264/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CDGRAPHICS_fuzzer-5711167941509120 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 9a9f0e239c1c6f5c96cc90ba673087f86ca1eabc) Signed-off-by: Michael Niedermayer --- libavcodec/cdgraphics.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/libavcodec/cdgraphics.c b/libavcodec/cdgraphics.c index be85e54288787..cf3f01a417bb3 100644 --- a/libavcodec/cdgraphics.c +++ b/libavcodec/cdgraphics.c @@ -81,11 +81,8 @@ static av_cold int cdg_decode_init(AVCodecContext *avctx) return AVERROR(ENOMEM); cc->transparency = -1; - avctx->width = CDG_FULL_WIDTH; - avctx->height = CDG_FULL_HEIGHT; avctx->pix_fmt = AV_PIX_FMT_PAL8; - - return 0; + return ff_set_dimensions(avctx, CDG_FULL_WIDTH, CDG_FULL_HEIGHT); } static void cdg_border_preset(CDGraphicsContext *cc, uint8_t *data) From 8cee4190f368c11b590bb95e2ea03fedbf5295a4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Tue, 5 Mar 2019 20:14:05 +0100 Subject: [PATCH 130/153] avcodec/dvbsubdec: Check object position Reference: ETSI EN 300 743 V1.2.1 7.2.2 Region composition segment Fixes: Timeout Fixes: 13325/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DVBSUB_fuzzer-5143979392237568 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit a8c5ae451184e879fc8ff1333c6f26f9542c8ebf) Signed-off-by: Michael Niedermayer --- libavcodec/dvbsubdec.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/libavcodec/dvbsubdec.c b/libavcodec/dvbsubdec.c index b59e8366570ee..bc4a17bde0ffa 100644 --- a/libavcodec/dvbsubdec.c +++ b/libavcodec/dvbsubdec.c @@ -1267,6 +1267,13 @@ static int dvbsub_parse_region_segment(AVCodecContext *avctx, display->y_pos = AV_RB16(buf) & 0xfff; buf += 2; + if (display->x_pos >= region->width || + display->y_pos >= region->height) { + av_log(avctx, AV_LOG_ERROR, "Object outside region\n"); + av_free(display); + return AVERROR_INVALIDDATA; + } + if ((object->type == 1 || object->type == 2) && buf+1 < buf_end) { display->fgcolor = *buf++; display->bgcolor = *buf++; From 77d244e7a937bf7e491d1783013e6b5a7c2ef797 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 14 Mar 2019 17:31:54 +0100 Subject: [PATCH 131/153] Update for 4.1.2 Signed-off-by: Michael Niedermayer --- Changelog | 33 +++++++++++++++++++++++++++++++++ RELEASE | 2 +- doc/Doxyfile | 2 +- 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 809d2967a2ca4..5d2d645d34e33 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,39 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. +version 4.1.2: +- avcodec/dvbsubdec: Check object position +- avcodec/cdgraphics: Use ff_set_dimensions() +- avformat/gdv: Check fps +- configure: use vpx_codec_vp8_dx/cx for libvpx-vp8 checking +- configure: add missing pthreads extralibs dependency for libvpx-vp9 +- avcodec/mpeg4videodec: Check idx in mpeg4_decode_studio_block() +- avcodec/dxv: Correct integer overflow in get_opcodes() +- avcodec/scpr: Fix use of uninitialized variable +- avcodec/qpeg: Limit copy in qpeg_decode_intra() to the available bytes +- avcodec/aic: Check remaining bits in aic_decode_coeffs() +- avcodec/gdv: Check for truncated tags in decompress_5() +- avcodec/bethsoftvideo: Check block_type +- avcodec/jpeg2000dwt: Fix integer overflow in dwt_decode97_int() +- avcodec/error_resilience: Use a symmetric check for skipping MV estimation +- avcodec/mlpdec: Insuffient typo +- avcodec/zmbv: obtain frame later +- avcodec/jvdec: Check available input space before decode8x8() +- avcodec/h264_direct: Fix overflow in POC comparission +- avformat/webmdashenc: Check id in adaption_sets +- avformat/http: Fix Out-of-Bounds access in process_line() +- avformat/ftp: Fix Out-of-Bounds Access and Information Leak in ftp.c:393 +- avcodec/htmlsubtitles: Fixes denial of service due to use of sscanf in inner loop for handling braces +- avcodec/htmlsubtitles: Fixes denial of service due to use of sscanf in inner loop for tag scaning +- avformat/matroskadec: Do not leak queued packets on sync errors +- avcodec/mpeg4videodec: Clear interlaced_dct for studio profile +- avformat/mov: Do not use reference stream in mov_read_sidx() if there is no reference stream +- avcodec/sbrdsp_fixed.c: remove input value limit for sbr_sum_square_c() +- avcodec/prores_ks: Fix luma quantization if q >= MAX_STORED_Q +- avformat/mov: fix hang while seek on a kind of fragmented mp4 +- avformat/async: fix assertion condition when draining buffer +- avcodec/cbs_av1: don't call cbs_av1_read_trailing_bits() when no bits remain in the OBU + version 4.1.1: - avformat/mov: validate chunk_count vs stsc_data - avformat/mov: require tfhd to begin parsing trun diff --git a/RELEASE b/RELEASE index 627a3f43a64f9..4d0dcda01c4c2 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -4.1.1 +4.1.2 diff --git a/doc/Doxyfile b/doc/Doxyfile index 3fcdbd74d1537..730c4c36b5440 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.1.1 +PROJECT_NUMBER = 4.1.2 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From dbef08b60f44469228d37c63ede587490492acb2 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 18 Mar 2019 17:25:58 -0300 Subject: [PATCH 132/153] avcodec/hevcdec: decode at most one slice reporting being the first in the picture Fixes deadlocks when decoding packets containing more than one of the aforementioned slices when using frame threads. Tested-by: Derek Buitenhuis Signed-off-by: James Almer (cherry picked from commit 70c8c8a818f39bc262565ec29fae2baffb3e1660) --- libavcodec/hevcdec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index a3b5c8cb71e5d..0dee673dace24 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -2924,6 +2924,10 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) } if (s->sh.first_slice_in_pic_flag) { + if (s->ref) { + av_log(s->avctx, AV_LOG_ERROR, "Two slices reporting being the first in the same frame.\n"); + goto fail; + } if (s->max_ra == INT_MAX) { if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) { s->max_ra = s->poc; From 7ce56329e71fc75512ef82f4794c43b629b8c488 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Fri, 8 Mar 2019 01:42:06 +0100 Subject: [PATCH 133/153] avcodec/clearvideo: Check remaining data in P frames Fixes: Timeout (19sec -> 419msec) Fixes: 13411/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_CLEARVIDEO_fuzzer-5733153811988480 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 41f93f941155f9f9dbb2d5e7f5d20b2238150836) Signed-off-by: Michael Niedermayer --- libavcodec/clearvideo.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libavcodec/clearvideo.c b/libavcodec/clearvideo.c index ad3012f7b789f..82df8f37522e6 100644 --- a/libavcodec/clearvideo.c +++ b/libavcodec/clearvideo.c @@ -555,6 +555,9 @@ static int clv_decode_frame(AVCodecContext *avctx, void *data, } else { int plane; + if (c->pmb_width * c->pmb_height > 8LL*(buf_size - bytestream2_tell(&gb))) + return AVERROR_INVALIDDATA; + if ((ret = ff_reget_buffer(avctx, c->pic)) < 0) return ret; From b429df281d50e960fb7f44659cac393a42cdfd35 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 10 Mar 2019 23:45:19 +0100 Subject: [PATCH 134/153] avcodec/dfa: Check the chunk header is not truncated Fixes: Timeout (11sec -> 3sec) Fixes: 13218/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_DFA_fuzzer-5661074316066816 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit f20760fadbc77483b9ff4b400b53ebb38ee33793) Signed-off-by: Michael Niedermayer --- libavcodec/dfa.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libavcodec/dfa.c b/libavcodec/dfa.c index 970175fb73468..c6106b9397d79 100644 --- a/libavcodec/dfa.c +++ b/libavcodec/dfa.c @@ -355,6 +355,8 @@ static int dfa_decode_frame(AVCodecContext *avctx, bytestream2_init(&gb, avpkt->data, avpkt->size); while (bytestream2_get_bytes_left(&gb) > 0) { + if (bytestream2_get_bytes_left(&gb) < 12) + return AVERROR_INVALIDDATA; bytestream2_skip(&gb, 4); chunk_size = bytestream2_get_le32(&gb); chunk_type = bytestream2_get_le32(&gb); From a7cb7a2e4314956e06a351333ff8096fab9afa7f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Thu, 21 Mar 2019 09:02:44 +0100 Subject: [PATCH 135/153] Changelog: update Signed-off-by: Michael Niedermayer --- Changelog | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog b/Changelog index 5d2d645d34e33..7df4e199bfc64 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,9 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. version 4.1.2: +- avcodec/dfa: Check the chunk header is not truncated +- avcodec/clearvideo: Check remaining data in P frames +- avcodec/hevcdec: decode at most one slice reporting being the first in the picture - avcodec/dvbsubdec: Check object position - avcodec/cdgraphics: Use ff_set_dimensions() - avformat/gdv: Check fps From abf36b76de63b4cdf07e0f8360422ff4758f7f70 Mon Sep 17 00:00:00 2001 From: James Almer Date: Sun, 24 Mar 2019 18:22:32 -0300 Subject: [PATCH 136/153] avcodec/av1_parser: don't abort parsing the first frame if extradata parsing fails The first frame contains the sequence header, which is needed to parse every following frame. This fixes parsing streams with broken extradata but correct packet data. Signed-off-by: James Almer (cherry picked from commit 699d0c2a30d5b2a10b6a0f459a35d665dc22b2f1) --- libavcodec/av1_parser.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libavcodec/av1_parser.c b/libavcodec/av1_parser.c index 8df66498f4d61..0390de0b3605d 100644 --- a/libavcodec/av1_parser.c +++ b/libavcodec/av1_parser.c @@ -68,8 +68,7 @@ static int av1_parser_parse(AVCodecParserContext *ctx, ret = ff_cbs_read(s->cbc, td, avctx->extradata, avctx->extradata_size); if (ret < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to parse extradata.\n"); - goto end; + av_log(avctx, AV_LOG_WARNING, "Failed to parse extradata.\n"); } ff_cbs_fragment_uninit(s->cbc, td); From 6972b353b4e00f784b9e70939e4d37dc61295e28 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 21 Mar 2019 15:37:26 -0300 Subject: [PATCH 137/153] avcodec/cbs_av1: fix range of values for Mastering Display Color Volume Metadata OBUs Signed-off-by: James Almer (cherry picked from commit 40490b3a63368bdc2403bf7415b214e6dc0a9a3a) --- libavcodec/cbs_av1_syntax_template.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libavcodec/cbs_av1_syntax_template.c b/libavcodec/cbs_av1_syntax_template.c index 48f4fab514a51..76eb90b279416 100644 --- a/libavcodec/cbs_av1_syntax_template.c +++ b/libavcodec/cbs_av1_syntax_template.c @@ -1637,15 +1637,18 @@ static int FUNC(metadata_hdr_mdcv)(CodedBitstreamContext *ctx, RWContext *rw, int err, i; for (i = 0; i < 3; i++) { - fcs(16, primary_chromaticity_x[i], 0, 50000, 1, i); - fcs(16, primary_chromaticity_y[i], 0, 50000, 1, i); + fbs(16, primary_chromaticity_x[i], 1, i); + fbs(16, primary_chromaticity_y[i], 1, i); } - fc(16, white_point_chromaticity_x, 0, 50000); - fc(16, white_point_chromaticity_y, 0, 50000); + fb(16, white_point_chromaticity_x); + fb(16, white_point_chromaticity_y); fc(32, luminance_max, 1, MAX_UINT_BITS(32)); - fc(32, luminance_min, 0, current->luminance_max >> 6); + // luminance_min must be lower than luminance_max. Convert luminance_max from + // 24.8 fixed point to 18.14 fixed point in order to compare them. + fc(32, luminance_min, 0, FFMIN(((uint64_t)current->luminance_max << 6) - 1, + MAX_UINT_BITS(32))); return 0; } From cb4768e7f20b6bc6eef28266ee9a3361967e65df Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 16 Mar 2019 02:30:57 +0100 Subject: [PATCH 138/153] avcodec/truemotion2: Fix integer overflow in tm2_null_res_block() Fixes: signed integer overflow: 1111638592 - -2122219136 cannot be represented in type 'int' Fixes: 13441/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_TRUEMOTION2_fuzzer-5732769815068672 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 1223696c725a8ea7e80498e6ccfab37eea179b76) Signed-off-by: Michael Niedermayer --- libavcodec/truemotion2.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libavcodec/truemotion2.c b/libavcodec/truemotion2.c index c583ff403218c..1aa7a4b870903 100644 --- a/libavcodec/truemotion2.c +++ b/libavcodec/truemotion2.c @@ -591,7 +591,8 @@ static inline void tm2_null_res_block(TM2Context *ctx, AVFrame *pic, int bx, int { int i; int ct; - int left, right, diff; + unsigned left, right; + int diff; int deltas[16]; TM2_INIT_POINTERS(); From ad0f4a7d10f91c63cceeb25010bec83311ad84fa Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 17 Mar 2019 11:14:26 +0100 Subject: [PATCH 139/153] avformat/mov: Fix potential integer overflow in entry check in mov_read_trun() No testcase Signed-off-by: Michael Niedermayer (cherry picked from commit ff13a92a6f8413402f5b3cacedda7c10d350b487) Signed-off-by: Michael Niedermayer --- libavformat/mov.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/mov.c b/libavformat/mov.c index 60309b486919d..caba256161551 100644 --- a/libavformat/mov.c +++ b/libavformat/mov.c @@ -4781,7 +4781,7 @@ static int mov_read_trun(MOVContext *c, AVIOContext *pb, MOVAtom atom) av_log(c->fc, AV_LOG_TRACE, "first sample flags 0x%x\n", first_sample_flags); // realloc space for new index entries - if((unsigned)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) { + if((uint64_t)st->nb_index_entries + entries >= UINT_MAX / sizeof(AVIndexEntry)) { entries = UINT_MAX / sizeof(AVIndexEntry) - st->nb_index_entries; av_log(c->fc, AV_LOG_ERROR, "Failed to add index entry\n"); } From 65f94b732a27cd7479c3fcff337bc247442016d8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 17 Mar 2019 15:18:20 +0100 Subject: [PATCH 140/153] avcodec/mpegpicture: Check size of edge_emu_buffer Fixes: OOM Fixes: 13710/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_MPEG4_fuzzer-5633152942342144 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Signed-off-by: Michael Niedermayer (cherry picked from commit 635067b75fce06928431ce9b9fcaee0c9b6b7280) Signed-off-by: Michael Niedermayer --- libavcodec/mpegpicture.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libavcodec/mpegpicture.c b/libavcodec/mpegpicture.c index c0e06900fe2a7..ecbd77d50e4f2 100644 --- a/libavcodec/mpegpicture.c +++ b/libavcodec/mpegpicture.c @@ -23,6 +23,7 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" #include "libavutil/pixdesc.h" +#include "libavutil/imgutils.h" #include "avcodec.h" #include "motion_est.h" @@ -57,6 +58,7 @@ do {\ int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me, ScratchpadContext *sc, int linesize) { +# define EMU_EDGE_HEIGHT (4 * 70) int alloc_size = FFALIGN(FFABS(linesize) + 64, 32); if (avctx->hwaccel) @@ -67,13 +69,16 @@ int ff_mpeg_framesize_alloc(AVCodecContext *avctx, MotionEstContext *me, return AVERROR_PATCHWELCOME; } + if (av_image_check_size2(alloc_size, EMU_EDGE_HEIGHT, avctx->max_pixels, AV_PIX_FMT_NONE, 0, avctx) < 0) + return AVERROR(ENOMEM); + // edge emu needs blocksize + filter length - 1 // (= 17x17 for halfpel / 21x21 for H.264) // VC-1 computes luma and chroma simultaneously and needs 19X19 + 9x9 // at uvlinesize. It supports only YUV420 so 24x24 is enough // linesize * interlaced * MBsize // we also use this buffer for encoding in encode_mb_internal() needig an additional 32 lines - FF_ALLOCZ_ARRAY_OR_GOTO(avctx, sc->edge_emu_buffer, alloc_size, 4 * 70, + FF_ALLOCZ_ARRAY_OR_GOTO(avctx, sc->edge_emu_buffer, alloc_size, EMU_EDGE_HEIGHT, fail); FF_ALLOCZ_ARRAY_OR_GOTO(avctx, me->scratchpad, alloc_size, 4 * 16 * 2, From daca529112d8cefa9d1f661b3493def303ba63c5 Mon Sep 17 00:00:00 2001 From: Carl Eugen Hoyos Date: Tue, 26 Mar 2019 13:32:11 +0100 Subject: [PATCH 141/153] lavc/bmp: Avoid a heap buffer overwrite for 1bpp input. Found by Mingi Cho, Seoyoung Kim, and Taekyoung Kwon of the Information Security Lab, Yonsei University. (cherry picked from commit 1e34014010dba9325fc5430934b51a61a5007c63) Signed-off-by: Michael Niedermayer --- libavcodec/bmp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libavcodec/bmp.c b/libavcodec/bmp.c index 65d239e4f8d8d..40010ac46f5a4 100644 --- a/libavcodec/bmp.c +++ b/libavcodec/bmp.c @@ -291,7 +291,7 @@ static int bmp_decode_frame(AVCodecContext *avctx, case 1: for (i = 0; i < avctx->height; i++) { int j; - for (j = 0; j < n; j++) { + for (j = 0; j < avctx->width >> 3; j++) { ptr[j*8+0] = buf[j] >> 7; ptr[j*8+1] = (buf[j] >> 6) & 1; ptr[j*8+2] = (buf[j] >> 5) & 1; @@ -301,6 +301,9 @@ static int bmp_decode_frame(AVCodecContext *avctx, ptr[j*8+6] = (buf[j] >> 1) & 1; ptr[j*8+7] = buf[j] & 1; } + for (j = 0; j < (avctx->width & 7); j++) { + ptr[avctx->width - (avctx->width & 7) + j] = buf[avctx->width >> 3] >> (7 - j) & 1; + } buf += n; ptr += linesize; } From f1ecebcdb72b5928b585ec8f07c3847927b4bf1d Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sat, 23 Mar 2019 20:55:08 +0100 Subject: [PATCH 142/153] avcodec/hevcdec: Avoid only partly skiping duplicate first slices Fixes: NULL pointer dereference and out of array access Fixes: 13871/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-5746167087890432 Fixes: 13845/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_HEVC_fuzzer-5650370728034304 This also fixes the return code for explode mode Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: James Almer Signed-off-by: Michael Niedermayer (cherry picked from commit 54655623a82632e7624714d7b2a3e039dc5faa7e) Signed-off-by: Michael Niedermayer --- libavcodec/hevcdec.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 0dee673dace24..afb3b1b55467d 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -485,6 +485,11 @@ static int hls_slice_header(HEVCContext *s) // Coded parameters sh->first_slice_in_pic_flag = get_bits1(gb); + if (s->ref && sh->first_slice_in_pic_flag) { + av_log(s->avctx, AV_LOG_ERROR, "Two slices reporting being the first in the same frame.\n"); + return 1; // This slice will be skiped later, do not corrupt state + } + if ((IS_IDR(s) || IS_BLA(s)) && sh->first_slice_in_pic_flag) { s->seq_decode = (s->seq_decode + 1) & 0xff; s->max_ra = INT_MAX; @@ -2915,6 +2920,11 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) ret = hls_slice_header(s); if (ret < 0) return ret; + if (ret == 1) { + ret = AVERROR_INVALIDDATA; + goto fail; + } + if ( (s->avctx->skip_frame >= AVDISCARD_BIDIR && s->sh.slice_type == HEVC_SLICE_B) || @@ -2924,10 +2934,6 @@ static int decode_nal_unit(HEVCContext *s, const H2645NAL *nal) } if (s->sh.first_slice_in_pic_flag) { - if (s->ref) { - av_log(s->avctx, AV_LOG_ERROR, "Two slices reporting being the first in the same frame.\n"); - goto fail; - } if (s->max_ra == INT_MAX) { if (s->nal_unit_type == HEVC_NAL_CRA_NUT || IS_BLA(s)) { s->max_ra = s->poc; From 1d720b37f0f3ae3d8e9fa2a991a8dca7deac7490 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 31 Mar 2019 23:31:47 +0200 Subject: [PATCH 143/153] Update for 4.1.3 Signed-off-by: Michael Niedermayer --- Changelog | 9 +++++++++ RELEASE | 2 +- doc/Doxyfile | 2 +- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Changelog b/Changelog index 7df4e199bfc64..6f4a623552a20 100644 --- a/Changelog +++ b/Changelog @@ -1,6 +1,15 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. +version 4.1.3: +- avcodec/hevcdec: Avoid only partly skiping duplicate first slices +- lavc/bmp: Avoid a heap buffer overwrite for 1bpp input. +- avcodec/mpegpicture: Check size of edge_emu_buffer +- avformat/mov: Fix potential integer overflow in entry check in mov_read_trun() +- avcodec/truemotion2: Fix integer overflow in tm2_null_res_block() +- avcodec/cbs_av1: fix range of values for Mastering Display Color Volume Metadata OBUs +- avcodec/av1_parser: don't abort parsing the first frame if extradata parsing fails + version 4.1.2: - avcodec/dfa: Check the chunk header is not truncated - avcodec/clearvideo: Check remaining data in P frames diff --git a/RELEASE b/RELEASE index 4d0dcda01c4c2..de197cc337f32 100644 --- a/RELEASE +++ b/RELEASE @@ -1 +1 @@ -4.1.2 +4.1.3 diff --git a/doc/Doxyfile b/doc/Doxyfile index 730c4c36b5440..f7b277adf69b5 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -38,7 +38,7 @@ PROJECT_NAME = FFmpeg # could be handy for archiving the generated documentation or if some version # control system is used. -PROJECT_NUMBER = 4.1.2 +PROJECT_NUMBER = 4.1.3 # Using the PROJECT_BRIEF tag one can provide an optional one line description # for a project that appears at the top of each page and should give viewer a From 58cd70201edc57b46fb4ad8c0810725f0bf80c86 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 28 Mar 2019 22:36:25 -0300 Subject: [PATCH 144/153] avformat/movenc: free eac3 private data only when closing the stream This makes sure the data is available when writing the moov atom during the second pass triggered by the faststart movflag. Fixes ticket #7780 Signed-off-by: James Almer (cherry picked from commit 27c94c57dc84da8125225fda7d241be57d19b391) --- libavformat/movenc.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 6dab5193b044e..2a45302ebbccb 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -544,8 +544,7 @@ static int mov_write_eac3_tag(AVIOContext *pb, MOVTrack *track) size = 2 + ((34 * (info->num_ind_sub + 1) + 7) >> 3); buf = av_malloc(size); if (!buf) { - size = AVERROR(ENOMEM); - goto end; + return AVERROR(ENOMEM); } init_put_bits(&pbc, buf, size); @@ -576,10 +575,6 @@ static int mov_write_eac3_tag(AVIOContext *pb, MOVTrack *track) av_free(buf); -end: - av_packet_unref(&info->pkt); - av_freep(&track->eac3_priv); - return size; } @@ -5947,6 +5942,11 @@ static void mov_free(AVFormatContext *s) av_freep(&mov->tracks[i].frag_info); av_packet_unref(&mov->tracks[i].cover_image); + if (mov->tracks[i].eac3_priv) { + struct eac3_info *info = mov->tracks[i].eac3_priv; + av_packet_unref(&info->pkt); + av_freep(&mov->tracks[i].eac3_priv); + } if (mov->tracks[i].vos_len) av_freep(&mov->tracks[i].vos_data); From 6c75df556f8ce97398789f363f5b323ae3abc920 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Sun, 31 Mar 2019 17:31:17 +0200 Subject: [PATCH 145/153] avcodec/rscc: Check that the to be uncompressed input is large enough Fixes: Out of array access Fixes: 13984/clusterfuzz-testcase-minimized-ffmpeg_AV_CODEC_ID_RSCC_fuzzer-5734128093233152 Found-by: continuous fuzzing process https://github.com/google/oss-fuzz/tree/master/projects/ffmpeg Reviewed-by: Paul B Mahol Signed-off-by: Michael Niedermayer (cherry picked from commit 3a0ec1511e7040845a0d1ce99fe2f30a0972b6d2) Signed-off-by: Michael Niedermayer --- libavcodec/rscc.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/rscc.c b/libavcodec/rscc.c index 7921f149ed5dd..69cb702777e62 100644 --- a/libavcodec/rscc.c +++ b/libavcodec/rscc.c @@ -198,6 +198,12 @@ static int rscc_decode_frame(AVCodecContext *avctx, void *data, /* If necessary, uncompress tiles, and hijack the bytestream reader */ if (packed_tiles_size != tiles_nb * TILE_SIZE) { uLongf length = tiles_nb * TILE_SIZE; + + if (bytestream2_get_bytes_left(gbc) < packed_tiles_size) { + ret = AVERROR_INVALIDDATA; + goto end; + } + inflated_tiles = av_malloc(length); if (!inflated_tiles) { ret = AVERROR(ENOMEM); From 4154f8967820ca734a77ce91bb590cd77649dee8 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer Date: Mon, 1 Apr 2019 10:33:02 +0200 Subject: [PATCH 146/153] Changelog: update Signed-off-by: Michael Niedermayer --- Changelog | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Changelog b/Changelog index 6f4a623552a20..5b76927071caf 100644 --- a/Changelog +++ b/Changelog @@ -2,6 +2,8 @@ Entries are sorted chronologically from oldest to youngest within each release, releases are sorted from youngest to oldest. version 4.1.3: +- avcodec/rscc: Check that the to be uncompressed input is large enough +- avformat/movenc: free eac3 private data only when closing the stream - avcodec/hevcdec: Avoid only partly skiping duplicate first slices - lavc/bmp: Avoid a heap buffer overwrite for 1bpp input. - avcodec/mpegpicture: Check size of edge_emu_buffer From ec82b3ecbbff1320be2b13f4a5ec41047810d315 Mon Sep 17 00:00:00 2001 From: James Almer Date: Mon, 25 Mar 2019 01:08:30 -0300 Subject: [PATCH 147/153] avcodec/cbs_av1: fix parsing spatial_id Reviewed-by: Mark Thompson Signed-off-by: James Almer (cherry picked from commit 461303f94ab64e0cbd502cddb6e79473f8f525a1) --- libavcodec/cbs_av1.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavcodec/cbs_av1.c b/libavcodec/cbs_av1.c index 4513287ef96e1..e4e3964118784 100644 --- a/libavcodec/cbs_av1.c +++ b/libavcodec/cbs_av1.c @@ -960,7 +960,7 @@ static int cbs_av1_read_unit(CodedBitstreamContext *ctx, if (obu->header.obu_extension_flag) { priv->temporal_id = obu->header.temporal_id; - priv->spatial_id = obu->header.temporal_id; + priv->spatial_id = obu->header.spatial_id; if (obu->header.obu_type != AV1_OBU_SEQUENCE_HEADER && obu->header.obu_type != AV1_OBU_TEMPORAL_DELIMITER && From 420fe39aff3dff17b064630963bbea1bdcdf79f4 Mon Sep 17 00:00:00 2001 From: Jeremy Dorfman Date: Mon, 8 Apr 2019 08:14:27 -0400 Subject: [PATCH 148/153] avformat/av1: Initialize padding in ff_isom_write_av1c Otherwise, AV1 encodes with FFmpeg trigger use-of-uninitialized-value warnings under MemorySanitizer, and the output buffer potentially changes from run to run. Signed-off-by: James Almer (cherry picked from commit bb5efd1727eeecc9be8f1402810c7ab72344eed3) --- libavformat/av1.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libavformat/av1.c b/libavformat/av1.c index a0aad436a690a..5fde8df97ea44 100644 --- a/libavformat/av1.c +++ b/libavformat/av1.c @@ -372,6 +372,7 @@ int ff_isom_write_av1c(AVIOContext *pb, const uint8_t *buf, int size) put_bits(&pbc, 1, seq_params.chroma_subsampling_x); put_bits(&pbc, 1, seq_params.chroma_subsampling_y); put_bits(&pbc, 2, seq_params.chroma_sample_position); + put_bits(&pbc, 8, 0); // padding flush_put_bits(&pbc); avio_write(pb, header, sizeof(header)); From cf7a5c655c04cd7d1a8912f390a7ae971ecf447b Mon Sep 17 00:00:00 2001 From: Tristan Matthews Date: Thu, 4 Apr 2019 12:56:26 -0400 Subject: [PATCH 149/153] avformat/matroskaenc: fix leak on error Signed-off-by: James Almer (cherry picked from commit 1ec777dcdd03b43d3d694c3b4532dccea0b419f0) --- libavformat/matroskaenc.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/libavformat/matroskaenc.c b/libavformat/matroskaenc.c index aed83aef70c14..ff1cba0145a68 100644 --- a/libavformat/matroskaenc.c +++ b/libavformat/matroskaenc.c @@ -694,8 +694,10 @@ static int put_flac_codecpriv(AVFormatContext *s, av_dict_set(&dict, "WAVEFORMATEXTENSIBLE_CHANNEL_MASK", buf, 0); len = ff_vorbiscomment_length(dict, vendor); - if (len >= ((1<<24) - 4)) + if (len >= ((1<<24) - 4)) { + av_dict_free(&dict); return AVERROR(EINVAL); + } data = av_malloc(len + 4); if (!data) { From 7c2dd1f969c9decf217f1b2117087c4b8918de22 Mon Sep 17 00:00:00 2001 From: Sergey Svechnikov Date: Mon, 22 Apr 2019 22:26:24 +0500 Subject: [PATCH 150/153] avcodec/cuviddec: improve progressive frame detection There are 2 types of problems when using adaptive deinterlace with cuvid: 1. Sometimes, in the middle of transcoding, cuvid outputs frames with visible horizontal lines (as though weave deinterlace method was chosen); 2. Occasionally, on scene changes, cuvid outputs a wrong frame, which should have been shown several seconds before (as if the frame was assigned some wrong PTS value). The reason is that sometimes CUVIDPARSERDISPINFO has property progressive_frame equal to 1 with interlaced videos. In order to fix the problem we should check if the video is interlaced or progressive in the beginning of a video sequence (cuvid_handle_video_sequence). And then we just use this information instead of the property progressive_frame in CUVIDPARSERDISPINFO (which is unreliable). Signed-off-by: Timo Rothenpieler --- libavcodec/cuviddec.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libavcodec/cuviddec.c b/libavcodec/cuviddec.c index f21273c07e903..67e39ac7192f4 100644 --- a/libavcodec/cuviddec.c +++ b/libavcodec/cuviddec.c @@ -70,6 +70,7 @@ typedef struct CuvidContext int deint_mode; int deint_mode_current; int64_t prev_pts; + int progressive_sequence; int internal_error; int decoder_flushing; @@ -228,6 +229,8 @@ static int CUDAAPI cuvid_handle_video_sequence(void *opaque, CUVIDEOFORMAT* form ? cudaVideoDeinterlaceMode_Weave : ctx->deint_mode; + ctx->progressive_sequence = format->progressive_sequence; + if (!format->progressive_sequence && ctx->deint_mode_current == cudaVideoDeinterlaceMode_Weave) avctx->flags |= AV_CODEC_FLAG_INTERLACED_DCT; else @@ -360,6 +363,9 @@ static int CUDAAPI cuvid_handle_picture_display(void *opaque, CUVIDPARSERDISPINF parsed_frame.dispinfo = *dispinfo; ctx->internal_error = 0; + // For some reason, dispinfo->progressive_frame is sometimes wrong. + parsed_frame.dispinfo.progressive_frame = ctx->progressive_sequence; + if (ctx->deint_mode_current == cudaVideoDeinterlaceMode_Weave) { av_fifo_generic_write(ctx->frame_queue, &parsed_frame, sizeof(CuvidParsedFrame), NULL); } else { From 7211e1ca9367f7f1a4a04983a66c7b1e2c9a3c92 Mon Sep 17 00:00:00 2001 From: James Almer Date: Thu, 25 Apr 2019 19:04:01 -0300 Subject: [PATCH 151/153] avformat/aacdec: fix demuxing of small frames 10 bytes (id3v2 header amount of bytes) were being read before any checks were made on the bitstream. The result was that we were overreading into the next frame if the current one was 8 or 9 bytes long. Fixes tickets #7271 and #7869. Signed-off-by: James Almer (cherry picked from commit d88193c2196cf5342424aaa7a44b046c71c2527a) --- libavformat/aacdec.c | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/libavformat/aacdec.c b/libavformat/aacdec.c index 685458b9114d0..e23abd0abf9ce 100644 --- a/libavformat/aacdec.c +++ b/libavformat/aacdec.c @@ -20,6 +20,7 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include "libavutil/avassert.h" #include "libavutil/intreadwrite.h" #include "avformat.h" #include "avio_internal.h" @@ -154,17 +155,8 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) { int ret, fsize; - // Parse all the ID3 headers between frames - while (1) { - ret = av_get_packet(s->pb, pkt, FFMAX(ID3v2_HEADER_SIZE, ADTS_HEADER_SIZE)); - if (ret >= ID3v2_HEADER_SIZE && ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { - if ((ret = handle_id3(s, pkt)) >= 0) { - continue; - } - } - break; - } - +retry: + ret = av_get_packet(s->pb, pkt, ADTS_HEADER_SIZE); if (ret < 0) return ret; @@ -174,8 +166,24 @@ static int adts_aac_read_packet(AVFormatContext *s, AVPacket *pkt) } if ((AV_RB16(pkt->data) >> 4) != 0xfff) { - av_packet_unref(pkt); - return AVERROR_INVALIDDATA; + // Parse all the ID3 headers between frames + int append = ID3v2_HEADER_SIZE - ADTS_HEADER_SIZE; + + av_assert2(append > 0); + ret = av_append_packet(s->pb, pkt, append); + if (ret != append) { + av_packet_unref(pkt); + return AVERROR(EIO); + } + if (!ff_id3v2_match(pkt->data, ID3v2_DEFAULT_MAGIC)) { + av_packet_unref(pkt); + return AVERROR_INVALIDDATA; + } + ret = handle_id3(s, pkt); + if (ret < 0) + return ret; + + goto retry; } fsize = (AV_RB32(pkt->data + 3) >> 13) & 0x1FFF; From 9810e67862984c424065cea93965252465957d90 Mon Sep 17 00:00:00 2001 From: Stephen Chen Date: Sat, 15 Jun 2019 13:28:27 +0800 Subject: [PATCH 152/153] ffmpeg-gl-transition from ffmpeg/4.1 --- .travis.yml | 14 +- libavfilter/Makefile | 1 + libavfilter/allfilters.c | 1 + libavfilter/vf_gltransition.c | 553 ++++++++++++++++++++++++++++++++++ 4 files changed, 556 insertions(+), 13 deletions(-) create mode 100644 libavfilter/vf_gltransition.c diff --git a/.travis.yml b/.travis.yml index 63f2051cb3f1f..5df421529862d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,30 +1,18 @@ language: c sudo: false -os: - - linux - - osx addons: apt: packages: - nasm - diffutils compiler: - - clang - gcc -matrix: - exclude: - - os: osx - compiler: gcc cache: directories: - ffmpeg-samples -before_install: - - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew update --all; fi -install: - - if [ "$TRAVIS_OS_NAME" == "osx" ]; then brew install nasm; fi script: - mkdir -p ffmpeg-samples - - ./configure --samples=ffmpeg-samples --cc=$CC + - ./configure --samples=ffmpeg-samples --cc=$CC --enable-gpl --enable-opengl --extra-libs='-lGLEW -lglfw' --enable-filter=gltransition --disable-shared --enable-static - make -j 8 - make fate-rsync - make check -j 8 diff --git a/libavfilter/Makefile b/libavfilter/Makefile index 4b78b29fada8e..692446876b06a 100644 --- a/libavfilter/Makefile +++ b/libavfilter/Makefile @@ -412,6 +412,7 @@ OBJS-$(CONFIG_YADIF_CUDA_FILTER) += vf_yadif_cuda.o vf_yadif_cuda.pt OBJS-$(CONFIG_ZMQ_FILTER) += f_zmq.o OBJS-$(CONFIG_ZOOMPAN_FILTER) += vf_zoompan.o OBJS-$(CONFIG_ZSCALE_FILTER) += vf_zscale.o +OBJS-$(CONFIG_GLTRANSITION_FILTER) += vf_gltransition.o OBJS-$(CONFIG_ALLRGB_FILTER) += vsrc_testsrc.o OBJS-$(CONFIG_ALLYUV_FILTER) += vsrc_testsrc.o diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c index c40c7e3a3c51a..04dcee2b8009d 100644 --- a/libavfilter/allfilters.c +++ b/libavfilter/allfilters.c @@ -393,6 +393,7 @@ extern AVFilter ff_vf_yadif_cuda; extern AVFilter ff_vf_zmq; extern AVFilter ff_vf_zoompan; extern AVFilter ff_vf_zscale; +extern AVFilter ff_vf_gltransition; extern AVFilter ff_vsrc_allrgb; extern AVFilter ff_vsrc_allyuv; diff --git a/libavfilter/vf_gltransition.c b/libavfilter/vf_gltransition.c new file mode 100644 index 0000000000000..5d09aca518ccf --- /dev/null +++ b/libavfilter/vf_gltransition.c @@ -0,0 +1,553 @@ +/** + * FFmpeg filter for applying GLSL transitions between video streams. + * + * @see https://gl-transitions.com/ + */ + +#include "libavutil/opt.h" +#include "internal.h" +#include "framesync.h" + +#ifndef __APPLE__ +#endif + +#ifdef __APPLE__ +# define __gl_h_ +# define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED +# include +#else +# include +#endif + +#ifdef GL_TRANSITION_USING_EGL +# include +#else +# include +#endif + +#include +#include +#include + +#define FROM (0) +#define TO (1) + +#define PIXEL_FORMAT (GL_RGB) + +#ifdef GL_TRANSITION_USING_EGL +static const EGLint configAttribs[] = { + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_BLUE_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_RED_SIZE, 8, + EGL_DEPTH_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT, + EGL_NONE}; +#endif +static const float position[12] = { + -1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f, -1.0f, 1.0f, 1.0f +}; + +static const GLchar *v_shader_source = + "attribute vec2 position;\n" + "varying vec2 _uv;\n" + "void main(void) {\n" + " gl_Position = vec4(position, 0, 1);\n" + " vec2 uv = position * 0.5 + 0.5;\n" + " _uv = vec2(uv.x, 1.0 - uv.y);\n" + "}\n"; + +static const GLchar *f_shader_template = + "varying vec2 _uv;\n" + "uniform sampler2D from;\n" + "uniform sampler2D to;\n" + "uniform float progress;\n" + "uniform float ratio;\n" + "uniform float _fromR;\n" + "uniform float _toR;\n" + "\n" + "vec4 getFromColor(vec2 uv) {\n" + " return texture2D(from, vec2(uv.x, 1.0 - uv.y));\n" + "}\n" + "\n" + "vec4 getToColor(vec2 uv) {\n" + " return texture2D(to, vec2(uv.x, 1.0 - uv.y));\n" + "}\n" + "\n" + "\n%s\n" + "void main() {\n" + " gl_FragColor = transition(_uv);\n" + "}\n"; + +// default to a basic fade effect +static const GLchar *f_default_transition_source = + "vec4 transition (vec2 uv) {\n" + " return mix(\n" + " getFromColor(uv),\n" + " getToColor(uv),\n" + " progress\n" + " );\n" + "}\n"; + +typedef struct { + const AVClass *class; + FFFrameSync fs; + + // input options + double duration; + double offset; + char *source; + + // timestamp of the first frame in the output, in the timebase units + int64_t first_pts; + + // uniforms + GLuint from; + GLuint to; + GLint progress; + GLint ratio; + GLint _fromR; + GLint _toR; + + // internal state + GLuint posBuf; + GLuint program; +#ifdef GL_TRANSITION_USING_EGL + EGLDisplay eglDpy; + EGLConfig eglCfg; + EGLSurface eglSurf; + EGLContext eglCtx; +#else + GLFWwindow *window; +#endif + + GLchar *f_shader_source; +} GLTransitionContext; + +#define OFFSET(x) offsetof(GLTransitionContext, x) +#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM + +static const AVOption gltransition_options[] = { + { "duration", "transition duration in seconds", OFFSET(duration), AV_OPT_TYPE_DOUBLE, {.dbl=1.0}, 0, DBL_MAX, FLAGS }, + { "offset", "delay before startingtransition in seconds", OFFSET(offset), AV_OPT_TYPE_DOUBLE, {.dbl=0.0}, 0, DBL_MAX, FLAGS }, + { "source", "path to the gl-transition source file (defaults to basic fade)", OFFSET(source), AV_OPT_TYPE_STRING, {.str = NULL}, CHAR_MIN, CHAR_MAX, FLAGS }, + {NULL} +}; + +FRAMESYNC_DEFINE_CLASS(gltransition, GLTransitionContext, fs); + +static GLuint build_shader(AVFilterContext *ctx, const GLchar *shader_source, GLenum type) +{ + GLuint shader = glCreateShader(type); + if (!shader || !glIsShader(shader)) { + return 0; + } + + glShaderSource(shader, 1, &shader_source, 0); + glCompileShader(shader); + + GLint status; + glGetShaderiv(shader, GL_COMPILE_STATUS, &status); + + return (status == GL_TRUE ? shader : 0); +} + +static int build_program(AVFilterContext *ctx) +{ + GLuint v_shader, f_shader; + GLTransitionContext *c = ctx->priv; + + if (!(v_shader = build_shader(ctx, v_shader_source, GL_VERTEX_SHADER))) { + av_log(ctx, AV_LOG_ERROR, "invalid vertex shader\n"); + return -1; + } + + char *source = NULL; + + if (c->source) { + FILE *f = fopen(c->source, "rb"); + + if (!f) { + av_log(ctx, AV_LOG_ERROR, "invalid transition source file \"%s\"\n", c->source); + return -1; + } + + fseek(f, 0, SEEK_END); + unsigned long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + source = malloc(fsize + 1); + fread(source, fsize, 1, f); + fclose(f); + + source[fsize] = 0; + } + + const char *transition_source = source ? source : f_default_transition_source; + + int len = strlen(f_shader_template) + strlen(transition_source); + c->f_shader_source = av_calloc(len, sizeof(*c->f_shader_source)); + if (!c->f_shader_source) { + return AVERROR(ENOMEM); + } + + snprintf(c->f_shader_source, len * sizeof(*c->f_shader_source), f_shader_template, transition_source); + av_log(ctx, AV_LOG_DEBUG, "\n%s\n", c->f_shader_source); + + if (source) { + free(source); + source = NULL; + } + + if (!(f_shader = build_shader(ctx, c->f_shader_source, GL_FRAGMENT_SHADER))) { + av_log(ctx, AV_LOG_ERROR, "invalid fragment shader\n"); + return -1; + } + + c->program = glCreateProgram(); + glAttachShader(c->program, v_shader); + glAttachShader(c->program, f_shader); + glLinkProgram(c->program); + + GLint status; + glGetProgramiv(c->program, GL_LINK_STATUS, &status); + return status == GL_TRUE ? 0 : -1; +} + +static void setup_vbo(GLTransitionContext *c) +{ + glGenBuffers(1, &c->posBuf); + glBindBuffer(GL_ARRAY_BUFFER, c->posBuf); + glBufferData(GL_ARRAY_BUFFER, sizeof(position), position, GL_STATIC_DRAW); + + GLint loc = glGetAttribLocation(c->program, "position"); + glEnableVertexAttribArray(loc); + glVertexAttribPointer(loc, 2, GL_FLOAT, GL_FALSE, 0, 0); +} + +static void setup_tex(AVFilterLink *fromLink) +{ + AVFilterContext *ctx = fromLink->dst; + GLTransitionContext *c = ctx->priv; + + { // from + glGenTextures(1, &c->from); + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, c->from); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fromLink->w, fromLink->h, 0, PIXEL_FORMAT, GL_UNSIGNED_BYTE, NULL); + + glUniform1i(glGetUniformLocation(c->program, "from"), 0); + } + + { // to + glGenTextures(1, &c->to); + glActiveTexture(GL_TEXTURE0 + 1); + glBindTexture(GL_TEXTURE_2D, c->to); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fromLink->w, fromLink->h, 0, PIXEL_FORMAT, GL_UNSIGNED_BYTE, NULL); + + glUniform1i(glGetUniformLocation(c->program, "to"), 1); + } +} + +static void setup_uniforms(AVFilterLink *fromLink) +{ + AVFilterContext *ctx = fromLink->dst; + GLTransitionContext *c = ctx->priv; + + c->progress = glGetUniformLocation(c->program, "progress"); + glUniform1f(c->progress, 0.0f); + + // TODO: this should be output ratio + c->ratio = glGetUniformLocation(c->program, "ratio"); + glUniform1f(c->ratio, fromLink->w / (float)fromLink->h); + + c->_fromR = glGetUniformLocation(c->program, "_fromR"); + glUniform1f(c->_fromR, fromLink->w / (float)fromLink->h); + + // TODO: initialize this in config_props for "to" input + c->_toR = glGetUniformLocation(c->program, "_toR"); + glUniform1f(c->_toR, fromLink->w / (float)fromLink->h); +} + +static int setup_gl(AVFilterLink *inLink) +{ + AVFilterContext *ctx = inLink->dst; + GLTransitionContext *c = ctx->priv; + + +#ifdef GL_TRANSITION_USING_EGL + //init EGL + // 1. Initialize EGL + c->eglDpy = eglGetDisplay(EGL_DEFAULT_DISPLAY); + EGLint major, minor; + eglInitialize(c->eglDpy, &major, &minor); + av_log(ctx, AV_LOG_DEBUG, "%d%d", major, minor); + // 2. Select an appropriate configuration + EGLint numConfigs; + EGLint pbufferAttribs[] = { + EGL_WIDTH, + inLink->w, + EGL_HEIGHT, + inLink->h, + EGL_NONE, + }; + eglChooseConfig(c->eglDpy, configAttribs, &c->eglCfg, 1, &numConfigs); + // 3. Create a surface + c->eglSurf = eglCreatePbufferSurface(c->eglDpy, c->eglCfg, + pbufferAttribs); + // 4. Bind the API + eglBindAPI(EGL_OPENGL_API); + // 5. Create a context and make it current + c->eglCtx = eglCreateContext(c->eglDpy, c->eglCfg, EGL_NO_CONTEXT, NULL); + eglMakeCurrent(c->eglDpy, c->eglSurf, c->eglSurf, c->eglCtx); +#else + //glfw + + glfwWindowHint(GLFW_VISIBLE, 0); + c->window = glfwCreateWindow(inLink->w, inLink->h, "", NULL, NULL); + if (!c->window) { + av_log(ctx, AV_LOG_ERROR, "setup_gl ERROR"); + return -1; + } + glfwMakeContextCurrent(c->window); + +#endif + +#ifndef __APPLE__ + glewExperimental = GL_TRUE; + glewInit(); +#endif + + glViewport(0, 0, inLink->w, inLink->h); + + int ret; + if((ret = build_program(ctx)) < 0) { + return ret; + } + + glUseProgram(c->program); + setup_vbo(c); + setup_uniforms(inLink); + setup_tex(inLink); + + return 0; +} + +static AVFrame *apply_transition(FFFrameSync *fs, + AVFilterContext *ctx, + AVFrame *fromFrame, + const AVFrame *toFrame) +{ + GLTransitionContext *c = ctx->priv; + AVFilterLink *fromLink = ctx->inputs[FROM]; + AVFilterLink *toLink = ctx->inputs[TO]; + AVFilterLink *outLink = ctx->outputs[0]; + AVFrame *outFrame; + + outFrame = ff_get_video_buffer(outLink, outLink->w, outLink->h); + if (!outFrame) { + return NULL; + } + + av_frame_copy_props(outFrame, fromFrame); + +#ifdef GL_TRANSITION_USING_EGL + eglMakeCurrent(c->eglDpy, c->eglSurf, c->eglSurf, c->eglCtx); +#else + glfwMakeContextCurrent(c->window); +#endif + + glUseProgram(c->program); + + const float ts = ((fs->pts - c->first_pts) / (float)fs->time_base.den) - c->offset; + const float progress = FFMAX(0.0f, FFMIN(1.0f, ts / c->duration)); + // av_log(ctx, AV_LOG_ERROR, "transition '%s' %llu %f %f\n", c->source, fs->pts - c->first_pts, ts, progress); + glUniform1f(c->progress, progress); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, c->from); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fromLink->w, fromLink->h, 0, PIXEL_FORMAT, GL_UNSIGNED_BYTE, fromFrame->data[0]); + + glActiveTexture(GL_TEXTURE0 + 1); + glBindTexture(GL_TEXTURE_2D, c->to); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, toLink->w, toLink->h, 0, PIXEL_FORMAT, GL_UNSIGNED_BYTE, toFrame->data[0]); + + glDrawArrays(GL_TRIANGLES, 0, 6); + glReadPixels(0, 0, outLink->w, outLink->h, PIXEL_FORMAT, GL_UNSIGNED_BYTE, (GLvoid *)outFrame->data[0]); + + av_frame_free(&fromFrame); + + return outFrame; +} + +static int blend_frame(FFFrameSync *fs) +{ + AVFilterContext *ctx = fs->parent; + GLTransitionContext *c = ctx->priv; + + AVFrame *fromFrame, *toFrame, *outFrame; + int ret; + + ret = ff_framesync_dualinput_get(fs, &fromFrame, &toFrame); + if (ret < 0) { + return ret; + } + + if (c->first_pts == AV_NOPTS_VALUE && fromFrame && fromFrame->pts != AV_NOPTS_VALUE) { + c->first_pts = fromFrame->pts; + } + + if (!toFrame) { + return ff_filter_frame(ctx->outputs[0], fromFrame); + } + + outFrame = apply_transition(fs, ctx, fromFrame, toFrame); + if (!outFrame) { + return AVERROR(ENOMEM); + } + + return ff_filter_frame(ctx->outputs[0], outFrame); +} + +static av_cold int init(AVFilterContext *ctx) +{ + GLTransitionContext *c = ctx->priv; + c->fs.on_event = blend_frame; + c->first_pts = AV_NOPTS_VALUE; + + +#ifndef GL_TRANSITION_USING_EGL + if (!glfwInit()) + { + return -1; + } +#endif + + return 0; +} + +static av_cold void uninit(AVFilterContext *ctx) { + GLTransitionContext *c = ctx->priv; + ff_framesync_uninit(&c->fs); + +#ifdef GL_TRANSITION_USING_EGL + if (c->eglDpy) { + glDeleteTextures(1, &c->from); + glDeleteTextures(1, &c->to); + glDeleteBuffers(1, &c->posBuf); + glDeleteProgram(c->program); + eglTerminate(c->eglDpy); + } +#else + if (c->window) { + glDeleteTextures(1, &c->from); + glDeleteTextures(1, &c->to); + glDeleteBuffers(1, &c->posBuf); + glDeleteProgram(c->program); + glfwDestroyWindow(c->window); + } +#endif + + if (c->f_shader_source) { + av_freep(&c->f_shader_source); + } +} + +static int query_formats(AVFilterContext *ctx) +{ + static const enum AVPixelFormat formats[] = { + AV_PIX_FMT_RGB24, + AV_PIX_FMT_NONE + }; + + return ff_set_common_formats(ctx, ff_make_format_list(formats)); +} + +static int activate(AVFilterContext *ctx) +{ + GLTransitionContext *c = ctx->priv; + return ff_framesync_activate(&c->fs); +} + +static int config_output(AVFilterLink *outLink) +{ + AVFilterContext *ctx = outLink->src; + GLTransitionContext *c = ctx->priv; + AVFilterLink *fromLink = ctx->inputs[FROM]; + AVFilterLink *toLink = ctx->inputs[TO]; + int ret; + + if (fromLink->format != toLink->format) { + av_log(ctx, AV_LOG_ERROR, "inputs must be of same pixel format\n"); + return AVERROR(EINVAL); + } + + if (fromLink->w != toLink->w || fromLink->h != toLink->h) { + av_log(ctx, AV_LOG_ERROR, "First input link %s parameters " + "(size %dx%d) do not match the corresponding " + "second input link %s parameters (size %dx%d)\n", + ctx->input_pads[FROM].name, fromLink->w, fromLink->h, + ctx->input_pads[TO].name, toLink->w, toLink->h); + return AVERROR(EINVAL); + } + + outLink->w = fromLink->w; + outLink->h = fromLink->h; + // outLink->time_base = fromLink->time_base; + outLink->frame_rate = fromLink->frame_rate; + + if ((ret = ff_framesync_init_dualinput(&c->fs, ctx)) < 0) { + return ret; + } + + return ff_framesync_configure(&c->fs); +} + +static const AVFilterPad gltransition_inputs[] = { + { + .name = "from", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = setup_gl, + }, + { + .name = "to", + .type = AVMEDIA_TYPE_VIDEO, + }, + {NULL} +}; + +static const AVFilterPad gltransition_outputs[] = { + { + .name = "default", + .type = AVMEDIA_TYPE_VIDEO, + .config_props = config_output, + }, + {NULL} +}; + +AVFilter ff_vf_gltransition = { + .name = "gltransition", + .description = NULL_IF_CONFIG_SMALL("OpenGL blend transitions"), + .priv_size = sizeof(GLTransitionContext), + .preinit = gltransition_framesync_preinit, + .init = init, + .uninit = uninit, + .query_formats = query_formats, + .activate = activate, + .inputs = gltransition_inputs, + .outputs = gltransition_outputs, + .priv_class = &gltransition_class, + .flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC +}; From 4e65fd6119d9b2c60bec3d2d6fada03eda0c8ea9 Mon Sep 17 00:00:00 2001 From: KbWen Date: Wed, 21 Aug 2019 11:31:20 +0800 Subject: [PATCH 153/153] add gl transition --- libavfilter/vf_gltransition.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/libavfilter/vf_gltransition.c b/libavfilter/vf_gltransition.c index 5d09aca518ccf..98f3661a7d8cc 100644 --- a/libavfilter/vf_gltransition.c +++ b/libavfilter/vf_gltransition.c @@ -376,17 +376,26 @@ static AVFrame *apply_transition(FFFrameSync *fs, // av_log(ctx, AV_LOG_ERROR, "transition '%s' %llu %f %f\n", c->source, fs->pts - c->first_pts, ts, progress); glUniform1f(c->progress, progress); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, c->from); + glPixelStorei(GL_UNPACK_ROW_LENGTH, fromFrame->linesize[0] / 3); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, fromLink->w, fromLink->h, 0, PIXEL_FORMAT, GL_UNSIGNED_BYTE, fromFrame->data[0]); glActiveTexture(GL_TEXTURE0 + 1); glBindTexture(GL_TEXTURE_2D, c->to); + glPixelStorei(GL_UNPACK_ROW_LENGTH, toFrame->linesize[0] / 3); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, toLink->w, toLink->h, 0, PIXEL_FORMAT, GL_UNSIGNED_BYTE, toFrame->data[0]); glDrawArrays(GL_TRIANGLES, 0, 6); + glPixelStorei(GL_PACK_ROW_LENGTH, outFrame->linesize[0] / 3); glReadPixels(0, 0, outLink->w, outLink->h, PIXEL_FORMAT, GL_UNSIGNED_BYTE, (GLvoid *)outFrame->data[0]); + glPixelStorei(GL_PACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 4); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + av_frame_free(&fromFrame); return outFrame;