From patchwork Sat Aug 25 11:24:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 10129 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:12c4:0:0:0:0:0 with SMTP id 65-v6csp4395747jap; Sat, 25 Aug 2018 04:24:22 -0700 (PDT) X-Google-Smtp-Source: ANB0VdYxThYWd2sYeTXgGOsjPbShHjRV5zpHO2S6t4jTxCk5Qou02x2aEjJcWOLVqBHiW179r6hL X-Received: by 2002:a1c:30c3:: with SMTP id w186-v6mr910047wmw.153.1535196262106; Sat, 25 Aug 2018 04:24:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1535196262; cv=none; d=google.com; s=arc-20160816; b=mppkZOOnNZr4D0TGFay973Is3WF8Ns4ukARkXpy0rnUkBk3aLVFfK3xIrIVHMj8mq8 dktbibljk/VWOwXyi8N2+m1zGTIDW+Crlj5th7NLiatLE+FtGUBxCznHEtybVr+i8bQ3 W3LntsQHt+6DA3At4yBf6xGEfsZ0g76FUpo0w8PU/Lct5fp+ieyNSNwUT7dUsAHgEqV8 VaOsjXAE4Tj7uotcWj07PV27h1Pun3FHJkfMmLlpZIZPEPC6q0cIGRAJgkv2dLEW1we2 ax9T2JQcdhblmVy3preglraYznEn7z8cpqWJhm/tMk2s9wPe7dWQrWTCJsFnt4kh94ON Wy2Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:mime-version:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:references:in-reply-to:message-id:date :to:from:dkim-signature:delivered-to:arc-authentication-results; bh=Y0+PTe14dZdQEn4UU00gB+Z0fNv6IrlvIqpge46fY+E=; b=D5Bv5FqI89LHq2NsT8m4sU+opTJQmfHm/dgM2dsr2SOGFj1Zd6m3pFgFIYKG7ze/0p pRjksmESKfNFbfItKVq3b4OXBnBucHcbCfdJOcVDGvkCJIXLKM4X7mP3ConLGOsJByxr xBf5oqdkR9S3DJDYQ6/h8ugM9RaZQ2h2T3C/KFfC+YlieETh4Tmw2b46FTR/Tmsc+B8R XAqGiJqCjdTP5XGqF8/t7Y3NZfpjOVk82yTMe+s/FkVuUyzAGWNfuiCMOeUg6BDMxOsy nBf6NZ3Usve17G3JJfhWd1hlltq6CoG6HtqMp+lO6I906WlZE07zYySWw3/Uxkt90zXf 9ghA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=MKCApPpk; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id z5-v6si2753675wmb.62.2018.08.25.04.24.21; Sat, 25 Aug 2018 04:24:22 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=MKCApPpk; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org; dmarc=fail (p=NONE sp=QUARANTINE dis=NONE) header.from=gmail.com Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 34923689E7A; Sat, 25 Aug 2018 14:24:17 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wm0-f67.google.com (mail-wm0-f67.google.com [74.125.82.67]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B63DF689AC5 for ; Sat, 25 Aug 2018 14:24:10 +0300 (EEST) Received: by mail-wm0-f67.google.com with SMTP id i134-v6so6280268wmf.0 for ; Sat, 25 Aug 2018 04:24:13 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references; bh=qk9xbtVYFdK+4tkAVWtaMKoKOFoMJOxBHjFAS84BcT0=; b=MKCApPpkJ0AYThOOKr8FfhNC0RSyUN91BSL1XyrzOZDZ3lkfm8KipARyxOT+YdahMG QzdP5kZYRVX13iSP17KuGA3/0L16KDm7R9ljQt6JYslyV26eemkcIAigXrGtjBi9brep Mqutq/3aE7AIVMtBfGrasL90g8jjXblAGMwdziE0khGhBPLyocis9TIEawQxIkiN9hTs otzv/X7SPFKfn+pPyFWsxKiwkBj+IUwSewqnnk5QD9xTKbe8WDldTiUri9f5/XPg297u oECIBn3dvmM0HcV9o69HUaa9vuOYXM5sEZBzPRPwfiDAzwPrhGZ9bpYNXMPa9lGjX4Au K9Ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references; bh=qk9xbtVYFdK+4tkAVWtaMKoKOFoMJOxBHjFAS84BcT0=; b=q+t62sXROBQQlmEyz88FJCeYinHt8xh97Cgri6DxORNW47rInKvv1sOSYidVAOqL3F 1tXn/lMa0sDM1l4qnORuMIq4TXaqQgjWmQqkPJ2UnwEBEpMz6wBPaO5heqpxRTZemTaI imXCmOfcDry6MNHuHQHeGzBHjncxo0OrCCDO+2qscVe9MeNVUD9S+UIZoBWP0HjNv/0D LEDdyXRHzc3c6xntT0AvBVqXLj1LEHBntWgShrcc8X08X7yg3+EIXqBhTSsNo43t+2MK tXVQXCNkt2rB3/Y+P9BrTRTwB2GwteMLlyw/2DGlpbhqTVepoTFTP/1Eim1Em6PcTYwW InGA== X-Gm-Message-State: APzg51CjAJHNoPsP29qS21inzRMMdTfHH4ZfT2cVdGHS8hXTmZQ6zZV5 qKg3uy8nQ/inq6YF4v8Y9f0Mh+wN X-Received: by 2002:a1c:e4c3:: with SMTP id b186-v6mr938661wmh.116.1535196252379; Sat, 25 Aug 2018 04:24:12 -0700 (PDT) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id 69-v6sm3745860wmb.27.2018.08.25.04.24.11 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 25 Aug 2018 04:24:11 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Sat, 25 Aug 2018 13:24:02 +0200 Message-Id: <20180825112402.7469-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180822221315.17383-1-onemda@gmail.com> References: <20180822221315.17383-1-onemda@gmail.com> Subject: [FFmpeg-devel] [PATCH] avcodec: add HYMT decoder X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paul B Mahol --- libavcodec/Makefile | 1 + libavcodec/allcodecs.c | 1 + libavcodec/avcodec.h | 1 + libavcodec/codec_desc.c | 7 ++ libavcodec/huffyuvdec.c | 174 +++++++++++++++++++++++++++------------- libavformat/riff.c | 1 + 6 files changed, 128 insertions(+), 57 deletions(-) diff --git a/libavcodec/Makefile b/libavcodec/Makefile index 9a309c348e..c9335f39fa 100644 --- a/libavcodec/Makefile +++ b/libavcodec/Makefile @@ -381,6 +381,7 @@ OBJS-$(CONFIG_HQ_HQA_DECODER) += hq_hqa.o hq_hqadata.o hq_hqadsp.o \ OBJS-$(CONFIG_HQX_DECODER) += hqx.o hqxvlc.o hqxdsp.o canopus.o OBJS-$(CONFIG_HUFFYUV_DECODER) += huffyuv.o huffyuvdec.o OBJS-$(CONFIG_HUFFYUV_ENCODER) += huffyuv.o huffyuvenc.o +OBJS-$(CONFIG_HYMT_DECODER) += huffyuv.o huffyuvdec.o OBJS-$(CONFIG_IDCIN_DECODER) += idcinvideo.o OBJS-$(CONFIG_IDF_DECODER) += bintext.o cga_data.o OBJS-$(CONFIG_IFF_ILBM_DECODER) += iff.o diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c index b1d1ef26c0..53ab6e0025 100644 --- a/libavcodec/allcodecs.c +++ b/libavcodec/allcodecs.c @@ -151,6 +151,7 @@ extern AVCodec ff_hq_hqa_decoder; extern AVCodec ff_hqx_decoder; extern AVCodec ff_huffyuv_encoder; extern AVCodec ff_huffyuv_decoder; +extern AVCodec ff_hymt_decoder; extern AVCodec ff_idcin_decoder; extern AVCodec ff_iff_ilbm_decoder; extern AVCodec ff_imm4_decoder; diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index 2a4be2ca4f..d428be4741 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -449,6 +449,7 @@ enum AVCodecID { AV_CODEC_ID_FITS, AV_CODEC_ID_IMM4, AV_CODEC_ID_PROSUMER, + AV_CODEC_ID_HYMT, /* various PCM "codecs" */ AV_CODEC_ID_FIRST_AUDIO = 0x10000, ///< A dummy id pointing at the start of audio codecs diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c index e611183599..362dc253c2 100644 --- a/libavcodec/codec_desc.c +++ b/libavcodec/codec_desc.c @@ -1668,6 +1668,13 @@ static const AVCodecDescriptor codec_descriptors[] = { .long_name = NULL_IF_CONFIG_SMALL("Brooktree ProSumer Video"), .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSY, }, + { + .id = AV_CODEC_ID_HYMT, + .type = AVMEDIA_TYPE_VIDEO, + .name = "hymt", + .long_name = NULL_IF_CONFIG_SMALL("HuffYUV MT"), + .props = AV_CODEC_PROP_INTRA_ONLY | AV_CODEC_PROP_LOSSLESS, + }, /* various PCM "codecs" */ { diff --git a/libavcodec/huffyuvdec.c b/libavcodec/huffyuvdec.c index 66357bfb40..4e00692631 100644 --- a/libavcodec/huffyuvdec.c +++ b/libavcodec/huffyuvdec.c @@ -905,54 +905,23 @@ static void add_median_prediction(HYuvContext *s, uint8_t *dst, const uint8_t *s s->hdsp.add_hfyu_median_pred_int16((uint16_t *)dst, (const uint16_t *)src, (const uint16_t *)diff, s->n-1, w, left, left_top); } } -static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, - AVPacket *avpkt) + +static int decode_slice(AVCodecContext *avctx, AVFrame *p, int height, + int buf_size, int y_offset, int table_size) { - const uint8_t *buf = avpkt->data; - int buf_size = avpkt->size; HYuvContext *s = avctx->priv_data; + int fake_ystride, fake_ustride, fake_vstride; const int width = s->width; const int width2 = s->width >> 1; - const int height = s->height; - int fake_ystride, fake_ustride, fake_vstride; - ThreadFrame frame = { .f = data }; - AVFrame *const p = data; - int table_size = 0, ret; - - if (buf_size < (width * height + 7)/8) - return AVERROR_INVALIDDATA; - - av_fast_padded_malloc(&s->bitstream_buffer, - &s->bitstream_buffer_size, - buf_size); - if (!s->bitstream_buffer) - return AVERROR(ENOMEM); - - s->bdsp.bswap_buf((uint32_t *) s->bitstream_buffer, - (const uint32_t *) buf, buf_size / 4); - - if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) - return ret; - - if (s->context) { - table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size); - if (table_size < 0) - return table_size; - } - - if ((unsigned) (buf_size - table_size) >= INT_MAX / 8) - return AVERROR_INVALIDDATA; + int ret; - if ((ret = init_get_bits(&s->gb, s->bitstream_buffer + table_size, - (buf_size - table_size) * 8)) < 0) + if ((ret = init_get_bits8(&s->gb, s->bitstream_buffer + table_size, buf_size - table_size)) < 0) return ret; fake_ystride = s->interlaced ? p->linesize[0] * 2 : p->linesize[0]; fake_ustride = s->interlaced ? p->linesize[1] * 2 : p->linesize[1]; fake_vstride = s->interlaced ? p->linesize[2] * 2 : p->linesize[2]; - s->last_slice_end = 0; - if (s->version > 2) { int plane; for(plane = 0; plane < 1 + 2*s->chroma + s->alpha; plane++) { @@ -1034,31 +1003,31 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_PATCHWELCOME; } else { leftv = - p->data[2][0] = get_bits(&s->gb, 8); + p->data[2][0 + y_offset * p->linesize[2]] = get_bits(&s->gb, 8); lefty = - p->data[0][1] = get_bits(&s->gb, 8); + p->data[0][1 + y_offset * p->linesize[0]] = get_bits(&s->gb, 8); leftu = - p->data[1][0] = get_bits(&s->gb, 8); - p->data[0][0] = get_bits(&s->gb, 8); + p->data[1][0 + y_offset * p->linesize[1]] = get_bits(&s->gb, 8); + p->data[0][0 + y_offset * p->linesize[0]] = get_bits(&s->gb, 8); switch (s->predictor) { case LEFT: case PLANE: decode_422_bitstream(s, width - 2); - lefty = s->llviddsp.add_left_pred(p->data[0] + 2, s->temp[0], + lefty = s->llviddsp.add_left_pred(p->data[0] + p->linesize[0] * y_offset + 2, s->temp[0], width - 2, lefty); if (!(s->flags & AV_CODEC_FLAG_GRAY)) { - leftu = s->llviddsp.add_left_pred(p->data[1] + 1, s->temp[1], width2 - 1, leftu); - leftv = s->llviddsp.add_left_pred(p->data[2] + 1, s->temp[2], width2 - 1, leftv); + leftu = s->llviddsp.add_left_pred(p->data[1] + p->linesize[1] * y_offset + 1, s->temp[1], width2 - 1, leftu); + leftv = s->llviddsp.add_left_pred(p->data[2] + p->linesize[2] * y_offset + 1, s->temp[2], width2 - 1, leftv); } - for (cy = y = 1; y < s->height; y++, cy++) { + for (cy = y = 1; y < height; y++, cy++) { uint8_t *ydst, *udst, *vdst; if (s->bitstream_bpp == 12) { decode_gray_bitstream(s, width); - ydst = p->data[0] + p->linesize[0] * y; + ydst = p->data[0] + p->linesize[0] * (y + y_offset); lefty = s->llviddsp.add_left_pred(ydst, s->temp[0], width, lefty); @@ -1067,15 +1036,15 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->llviddsp.add_bytes(ydst, ydst - fake_ystride, width); } y++; - if (y >= s->height) + if (y >= height) break; } draw_slice(s, p, y); - ydst = p->data[0] + p->linesize[0] * y; - udst = p->data[1] + p->linesize[1] * cy; - vdst = p->data[2] + p->linesize[2] * cy; + ydst = p->data[0] + p->linesize[0] * (y + y_offset); + udst = p->data[1] + p->linesize[1] * (cy + y_offset); + vdst = p->data[2] + p->linesize[2] * (cy + y_offset); decode_422_bitstream(s, width); lefty = s->llviddsp.add_left_pred(ydst, s->temp[0], @@ -1185,7 +1154,7 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, } else { int y; uint8_t left[4]; - const int last_line = (height - 1) * p->linesize[0]; + const int last_line = (y_offset + height - 1) * p->linesize[0]; if (s->bitstream_bpp == 32) { left[A] = p->data[0][last_line + A] = get_bits(&s->gb, 8); @@ -1208,17 +1177,17 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + last_line + 4, s->temp[0], width - 1, left); - for (y = s->height - 2; y >= 0; y--) { // Yes it is stored upside down. + for (y = height - 2; y >= 0; y--) { // Yes it is stored upside down. decode_bgr_bitstream(s, width); - s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + p->linesize[0] * y, + s->hdsp.add_hfyu_left_pred_bgr32(p->data[0] + p->linesize[0] * (y + y_offset), s->temp[0], width, left); if (s->predictor == PLANE) { if (s->bitstream_bpp != 32) left[A] = 0; - if (y < s->height - 1 - s->interlaced) { - s->llviddsp.add_bytes(p->data[0] + p->linesize[0] * y, - p->data[0] + p->linesize[0] * y + + if (y < height - 1 - s->interlaced) { + s->llviddsp.add_bytes(p->data[0] + p->linesize[0] * (y + y_offset), + p->data[0] + p->linesize[0] * (y + y_offset) + fake_ystride, 4 * width); } } @@ -1236,7 +1205,82 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, return AVERROR_PATCHWELCOME; } } - emms_c(); + + return 0; +} + +static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, + AVPacket *avpkt) +{ + const uint8_t *buf = avpkt->data; + int buf_size = avpkt->size; + HYuvContext *s = avctx->priv_data; + const int width = s->width; + const int height = s->height; + ThreadFrame frame = { .f = data }; + AVFrame *const p = data; + int slice, table_size = 0, ret, nb_slices; + unsigned slices_info_offset; + int slice_height; + + if (buf_size < (width * height + 7)/8) + return AVERROR_INVALIDDATA; + + av_fast_padded_malloc(&s->bitstream_buffer, + &s->bitstream_buffer_size, + buf_size); + if (!s->bitstream_buffer) + return AVERROR(ENOMEM); + + s->bdsp.bswap_buf((uint32_t *) s->bitstream_buffer, + (const uint32_t *) buf, buf_size / 4); + + if ((ret = ff_thread_get_buffer(avctx, &frame, 0)) < 0) + return ret; + + if (s->context) { + table_size = read_huffman_tables(s, s->bitstream_buffer, buf_size); + if (table_size < 0) + return table_size; + } + + if ((unsigned) (buf_size - table_size) >= INT_MAX / 8) + return AVERROR_INVALIDDATA; + + s->last_slice_end = 0; + + if (avctx->codec_id == AV_CODEC_ID_HYMT && + (buf_size > 32 && AV_RL32(avpkt->data + buf_size - 16) == 0)) { + slices_info_offset = AV_RL32(avpkt->data + buf_size - 4); + slice_height = AV_RL32(avpkt->data + buf_size - 8); + nb_slices = AV_RL32(avpkt->data + buf_size - 12); + if (nb_slices * 8LL + slices_info_offset > buf_size - 16) + return AVERROR_INVALIDDATA; + } else { + slice_height = height; + nb_slices = 1; + } + + for (slice = 0; slice < nb_slices; slice++) { + int y_offset, slice_offset, slice_size; + + if (nb_slices > 1) { + slice_offset = AV_RL32(avpkt->data + slices_info_offset + slice * 8); + slice_size = AV_RL32(avpkt->data + slices_info_offset + slice * 8 + 4); + y_offset = height - (slice + 1) * slice_height; + s->bdsp.bswap_buf((uint32_t *)s->bitstream_buffer, + (const uint32_t *)(buf + slice_offset), slice_size / 4); + } else { + y_offset = 0; + slice_offset = 0; + slice_size = buf_size; + } + + ret = decode_slice(avctx, p, slice_height, slice_size, y_offset, table_size); + emms_c(); + if (ret < 0) + return ret; + } *got_frame = 1; @@ -1272,3 +1316,19 @@ AVCodec ff_ffvhuff_decoder = { .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), }; #endif /* CONFIG_FFVHUFF_DECODER */ + +#if CONFIG_HYMT_DECODER +AVCodec ff_hymt_decoder = { + .name = "hymt", + .long_name = NULL_IF_CONFIG_SMALL("HuffYUV MT"), + .type = AVMEDIA_TYPE_VIDEO, + .id = AV_CODEC_ID_HYMT, + .priv_data_size = sizeof(HYuvContext), + .init = decode_init, + .close = decode_end, + .decode = decode_frame, + .capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DRAW_HORIZ_BAND | + AV_CODEC_CAP_FRAME_THREADS, + .init_thread_copy = ONLY_IF_THREADS_ENABLED(decode_init_thread_copy), +}; +#endif /* CONFIG_HYMT_DECODER */ diff --git a/libavformat/riff.c b/libavformat/riff.c index cf27d0dfd5..7385125bbb 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -472,6 +472,7 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_SRGC, MKTAG('S', 'R', 'G', 'C') }, { AV_CODEC_ID_IMM4, MKTAG('I', 'M', 'M', '4') }, { AV_CODEC_ID_PROSUMER, MKTAG('B', 'T', '2', '0') }, + { AV_CODEC_ID_HYMT, MKTAG('H', 'Y', 'M', 'T') }, { AV_CODEC_ID_NONE, 0 } };