From patchwork Wed Aug 22 22:13:15 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: 10059 Delivered-To: ffmpegpatchwork@gmail.com Received: by 2002:a02:12c4:0:0:0:0:0 with SMTP id 65-v6csp1375916jap; Wed, 22 Aug 2018 15:20:37 -0700 (PDT) X-Google-Smtp-Source: AA+uWPxlIdVOGEpKvT8QjA9LK2f379e4H+e9uC3c4vc3ecIMSF/hX9+blOdBpHczPvjBYcwdkomy X-Received: by 2002:adf:f906:: with SMTP id b6-v6mr32353825wrr.28.1534976437242; Wed, 22 Aug 2018 15:20:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1534976437; cv=none; d=google.com; s=arc-20160816; b=t1duw3/rRGklUSBAi1RltDP4zQmGyaxbTYkfokXOoaI3lLG7glBak62ltphmwIqC/w b2MBVR/XxbagjJ301zkvy6EqCs/jTbWEDXUzk+/+Ri1zp1uVWG1B4mXPcMyWkOIgZzZn Rj9Lzus4R7KEjAeRXAUpia3l9n5ko5VHtrqjsL5PJZBIb1Vfgk4ubQLqJ/xV1v2EsAgV AmYrvH2bJtzVJJ0NiFSz4TFEDKopUKyAAZQqDm8l6x7ZKMdPOo/N93cBPERTjpcaLYnB 4XiEL2AeIuzSny8SWpLdZOk2FBefALamOn7KTzXNTdAY9sUwFPBcQyDNYC2OzaJ3/fzL OrCQ== 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:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=c4ursQrbXO9WP1DutH2DdTxuH2CtZO2wVXD4L+xmQYA=; b=lt/iKuzq+krBiI1UYMBRGWtjOve/GHO7ZN+MClfBmpV4VETQ1ZFb/2gcgEUDiht8TI TxwzKXt3CbjVZWLgEeNH2nnbzLpXIPBbFoqKMFTCKyta40njHHk5eHkoWiM5bbnX7xTK MQg1HI87Ytu1pj1m8JXbqgcC2XRv8NnEYVUmy85inik5E43DCpqr7K3xIyJ1NIF6EJaw TfFQ8CzjPS9JcrGO4WO5tviSuOhgzE3Hcvh8ew9B6TN3qJ7jSpiiH4PNRCNQfoCH8kyb UEQLtUjPbn1+WlUbT44EhEseomFEFrxbLL5vxvGYPijpESz1bYyC6+QunV7os5GZgMSB zOCQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=eb244HG1; 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 s7-v6si2374276wrv.266.2018.08.22.15.20.36; Wed, 22 Aug 2018 15:20:37 -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=eb244HG1; 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 AC2B7689BA7; Thu, 23 Aug 2018 01:20:33 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f66.google.com (mail-wr1-f66.google.com [209.85.221.66]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 972FD689723 for ; Thu, 23 Aug 2018 01:20:26 +0300 (EEST) Received: by mail-wr1-f66.google.com with SMTP id a108-v6so2841846wrc.13 for ; Wed, 22 Aug 2018 15:20:28 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=JILetFXyZnEYYgEiJnRQb3nSfcnNMBF3mGTrU1MSk/M=; b=eb244HG1/1hsmEfhKr7eNGe37ZF9P99iVApckV7KBQfAOwvlvZ9760oOn+jiCfgHEH v05a4Bct0ApDIQnk1PSNedjn5WmimR789YDA5hI3tiY/plGduIjcd1XOlA+TfS97DtFX 5tgs9fOmGSfZyXtNKrUhqIIsVEustZ8GegB2kA/9a0kTPpB+jORrKDqCfaxlcnqqKHdo RB4bE2WUX6PH3mNrEnXBXFeFOwJJdPNbn8/KiKNLX8qsOEBBdpIjhVVbT/yVlgk09MSn ZcabA6JvSOm5jxIrtLuFQrbTR+V79qc8XnK/3onai4SC9cwfi0hbqrYmve8edlGbrqrq tjYQ== 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; bh=JILetFXyZnEYYgEiJnRQb3nSfcnNMBF3mGTrU1MSk/M=; b=mezkKPVU6ouabq2Oo6HQ3la6399zuEdh76wf7YHmWSPwHIE063CI0cGH8Swups/VBs 3V3803N0MJqkQoYfn3Qd4zzVTvyzeAfk/xT3CZQbdiz89+UFEE9Hl2SrnNTA7geAmfk5 RiuxUOIjELsKaNOCDhuOqjdDluto7te4mVlts1AEjXp1Os17mxvbbY475sWhMl2rahJ8 uOgGF9jnbpaD4637zClRX1GB+kyhBx0vcUB6sqNWyxRcnRU4p3wu4OJHc/9A2wPufs70 IOMiHDDYvxEKgXK/SSVnIacyPyM3yPMyGbSUI/H5/caogko+JDO6yx2UI7QdwrPKdQIV tORw== X-Gm-Message-State: AOUpUlFxbrKrrwqn4yfzAqPIvU6VxqVFOIG6t30wgOxDSl47L2Wf/Ycp 2kueP/yvCH8XQPKcrvyoYuROD1Cm X-Received: by 2002:adf:eb87:: with SMTP id t7-v6mr35729768wrn.123.1534976008891; Wed, 22 Aug 2018 15:13:28 -0700 (PDT) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id a37-v6sm6286092wrc.21.2018.08.22.15.13.27 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 22 Aug 2018 15:13:28 -0700 (PDT) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Thu, 23 Aug 2018 00:13:15 +0200 Message-Id: <20180822221315.17383-1-onemda@gmail.com> X-Mailer: git-send-email 2.17.1 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..b5b65510ed 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) { - 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, buf_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; + } else { + y_offset = 0; + slice_offset = 0; + slice_size = buf_size; + } + s->bdsp.bswap_buf((uint32_t *)s->bitstream_buffer, + (const uint32_t *)(buf + slice_offset), slice_size / 4); + + ret = decode_slice(avctx, p, slice_height, slice_size, y_offset); + 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 } };