From patchwork Sat Dec 30 17:09:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paul B Mahol X-Patchwork-Id: 7036 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.79.195 with SMTP id r64csp11809813jad; Sat, 30 Dec 2017 09:10:17 -0800 (PST) X-Google-Smtp-Source: ACJfBovD1f6X3lieA0Vs2IUKgLgaApYum4++7fAR5Idnpm4VPNhJgamesWhwyVt0sQoFMrSPNEQe X-Received: by 10.28.199.75 with SMTP id x72mr28510326wmf.87.1514653817159; Sat, 30 Dec 2017 09:10:17 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1514653817; cv=none; d=google.com; s=arc-20160816; b=CjO8IFbquU7MXmTbnmZBb4qZzAsjQyBQ3bIreCqLgU4wHJJkrPmym4lcTxf03Ca6GH VN+yeSViWrq1vUFnICSU2gUKqBshcsCxR3ICqpyzZo/nQOqngWpjCbZukmWo6qrA0WNm e768WvcYNW7SkrM7ZpKy6G3VFgiOGdP+Wq/FknB2FfXArSqfpNqPY8L3KEX9VKK9+sVs Xg5SVaT1Kv5pLPyq7YbUXxaqRnRMqbZv8wANVUVC1dCwU8+P4326eRs+jML+RhoojNGm es85vLU+r1rzpaiAXxzKRqdvql+rzpFrl88LbXpyHqU3Jse4fLcDi9q0iUm858fsxMEL BUUQ== 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=xeZZaV/x/BUk/8L9IBhvtNP1xw4uinud2t0GxrQQHwo=; b=eFF3SORxtGqxnojB8zfindQ0K6o/HwUMjYYhWIx7liT6cB8W2ZXyrMyW+NalNL4Evz xdRWX+L9LmXVQoIfGaKpdOvvH/RSoy+ICD5MvIVOtcUSC13qSaHnfqFYb+EzK9DeC6mV lBz3sLZwOtDkBvIsoggIsh81jdZundg0fzqbSaxSNJ58rVHgJXcITSDtHflfjDW6FDNf CgxdjKmDY5mISAHREImla4QQg9y2dno3SJlyC0gNYtUWai2biUrHu1eXgJAZwzwpaVDi vxXbKQ2yAniVRR833K2YbbnuExffyV9mdOze6Gsh8igVbeAxXjLPPYt5YMY8vYtI3ETc THNw== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=OKIGRYhW; 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=NONE 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 o96si26691449wrb.247.2017.12.30.09.10.16; Sat, 30 Dec 2017 09:10:17 -0800 (PST) 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=OKIGRYhW; 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=NONE 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 AE94C689DB5; Sat, 30 Dec 2017 19:10:00 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr0-f196.google.com (mail-wr0-f196.google.com [209.85.128.196]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id B645B689D99 for ; Sat, 30 Dec 2017 19:09:54 +0200 (EET) Received: by mail-wr0-f196.google.com with SMTP id l19so31460227wrc.2 for ; Sat, 30 Dec 2017 09:10:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id; bh=RK8VtENSp0UEduR+Lc8l3zBbQb3GnnJhhfr13kyVH28=; b=OKIGRYhW5bNxd7BEXcLTo2zuemPOrkNTq6TzmbzmwReuFQuAo1PGoWPFmp/yN8iP1M lDiWkMyRxDH/KGVICg8ytbU1rT04eq7Rom3tMybbTy9vvn64593ZcM1vWDXQFtQ/VUZf ZWF/uusSrpER8JVrm/PpWjLjlx8bAPEp/sfVOYEjlgtzSrhVbdrmLuDyJYONU/Ok1xY/ UAOSpvv+x9iWufdbQnZk1KLthfN+D/0nbeTKBSU5gM9xRbmtzJtqDi6HDCBn7xTAjEHu Hebf/zQAKYfZX32QatZ5ke1pspWTYlZx54uHDAJnZwQfoJ1g0rV7ecgIehpoV100um1Y pGGQ== 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=RK8VtENSp0UEduR+Lc8l3zBbQb3GnnJhhfr13kyVH28=; b=GeH6H/nafQ/x8tV3bVeyYK/zo4I42JInAdiq9z6K6WEA5eVtpXWu0YyOK8ZWKwDavm XQ1V2RYbqnHogrudynHSa+B5/wKY0pjF+upDkXoRnEJWL/qb4NExk/P/giG6cuQG8Ufc PEIImuTwjSx8pp+59nrMB7Fb7NZ8a26giGqUHs0fW/r4Z+Yg0zRZSSy/VlDXG4MgtQsi qG/LzavAObxq2hbATzOdO5BF0CZRnp/QHepBnHw/Rgza9gRUef8muuFKBz7gpShtRnrY tmAhE/2FbV+vhILJ13Dl3sMIeHV4UyaN+Hz1YBP+qhfkjLmjrwjOwMvonD8NyD1QW0n0 mo7Q== X-Gm-Message-State: AKGB3mLoLH3SW5jLgfRgEDlM5CEj6JBQmWiXjgSn5RaFAmJmlPdTIkdp +plarTNoLiTwDCtu86evBQDK8g== X-Received: by 10.223.195.46 with SMTP id n43mr124862wrf.212.1514653809063; Sat, 30 Dec 2017 09:10:09 -0800 (PST) Received: from localhost.localdomain ([94.250.174.60]) by smtp.gmail.com with ESMTPSA id y53sm26841949wry.19.2017.12.30.09.10.07 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 30 Dec 2017 09:10:08 -0800 (PST) From: Paul B Mahol To: ffmpeg-devel@ffmpeg.org Date: Sat, 30 Dec 2017 18:09:23 +0100 Message-Id: <20171230170923.9396-1-onemda@gmail.com> X-Mailer: git-send-email 2.11.0 Subject: [FFmpeg-devel] [PATCH] avcodec/utvideodec: add support for UMH2, UMY2, UMH4, UMY4, UMRA, UMRG 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" These are new modes which are supposed to be more SIMD friendly. Signed-off-by: Paul B Mahol --- libavcodec/utvideo.h | 8 +- libavcodec/utvideodec.c | 199 +++++++++++++++++++++++++++++++++++++++--------- libavformat/riff.c | 6 ++ 3 files changed, 174 insertions(+), 39 deletions(-) diff --git a/libavcodec/utvideo.h b/libavcodec/utvideo.h index a8117851a7..cf0bb28c44 100644 --- a/libavcodec/utvideo.h +++ b/libavcodec/utvideo.h @@ -72,17 +72,23 @@ typedef struct UtvideoContext { LLVidDSPContext llviddsp; LLVidEncDSPContext llvidencdsp; - uint32_t frame_info_size, flags, frame_info; + uint32_t frame_info_size, flags, frame_info, offset; int planes; int slices; int compression; int interlaced; int frame_pred; int pro; + int pack; ptrdiff_t slice_stride; uint8_t *slice_bits, *slice_buffer[4]; int slice_bits_size; + + const uint8_t *packed_stream[4][256]; + size_t packed_stream_size[4][256]; + const uint8_t *control_stream[4][256]; + size_t control_stream_size[4][256]; } UtvideoContext; typedef struct HuffEntry { diff --git a/libavcodec/utvideodec.c b/libavcodec/utvideodec.c index c6076811d1..f019a40e8b 100644 --- a/libavcodec/utvideodec.c +++ b/libavcodec/utvideodec.c @@ -247,9 +247,50 @@ static int decode_plane(UtvideoContext *c, int plane_no, int sstart, send; VLC vlc; GetBitContext gb; - int prev, fsym; + int ret, prev, fsym; const int cmask = compute_cmask(plane_no, c->interlaced, c->avctx->pix_fmt); + if (c->pack) { + send = 0; + for (slice = 0; slice < c->slices; slice++) { + GetBitContext cbit, pbit; + uint8_t *dest, *p; + + ret = init_get_bits8(&cbit, c->control_stream[plane_no][slice], c->control_stream_size[plane_no][slice]); + if (ret < 0) + return ret; + + ret = init_get_bits8(&pbit, c->packed_stream[plane_no][slice], c->packed_stream_size[plane_no][slice]); + if (ret < 0) + return ret; + + sstart = send; + send = (height * (slice + 1) / c->slices) & cmask; + dest = dst + sstart * stride; + + for (p = dest; p < dst + send * stride; p += 8) { + int bits = get_bits_le(&cbit, 3); + + if (bits == 0) { + *(uint64_t *) p = 0; + } else { + uint32_t sub = 0x80 >> (8 - (bits + 1)), add; + int k; + + for (k = 0; k < 8; k++) { + + p[k] = get_bits_le(&pbit, bits + 1); + add = (~p[k] & sub) << (8 - bits); + p[k] -= sub; + p[k] += add; + } + } + } + } + + return 0; + } + if (build_huff(src, &vlc, &fsym)) { av_log(c->avctx, AV_LOG_ERROR, "Cannot build Huffman codes\n"); return AVERROR_INVALIDDATA; @@ -566,7 +607,43 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, /* parse plane structure to get frame flags and validate slice offsets */ bytestream2_init(&gb, buf, buf_size); - if (c->pro) { + + if (c->pack) { + GetByteContext pb; + uint32_t nb_cbs; + const uint8_t *packed_stream; + const uint8_t *control_stream; + + c->frame_info = PRED_GRADIENT << 8; + + if (bytestream2_get_byte(&gb) != 1) + return AVERROR_INVALIDDATA; + bytestream2_skip(&gb, 3); + c->offset = bytestream2_get_le32(&gb); + + if (buf_size <= c->offset + 8LL) + return AVERROR_INVALIDDATA; + + bytestream2_init(&pb, buf + 8 + c->offset, buf_size - 8 - c->offset); + nb_cbs = bytestream2_get_le32(&pb); + control_stream = buf + 8 + c->offset - nb_cbs; + + packed_stream = buf + 8; + for (i = 0; i < c->planes; i++) { + for (j = 0; j < c->slices; j++) { + c->packed_stream[i][j] = packed_stream; + c->packed_stream_size[i][j] = bytestream2_get_le32(&pb); + packed_stream += c->packed_stream_size[i][j]; + } + } + for (i = 0; i < c->planes; i++) { + for (j = 0; j < c->slices; j++) { + c->control_stream[i][j] = control_stream; + c->control_stream_size[i][j] = bytestream2_get_le32(&pb); + control_stream += c->control_stream_size[i][j]; + } + } + } else if (c->pro) { if (bytestream2_get_bytes_left(&gb) < c->frame_info_size) { av_log(avctx, AV_LOG_ERROR, "Not enough data for frame information\n"); return AVERROR_INVALIDDATA; @@ -635,12 +712,14 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *got_frame, max_slice_size += 4*avctx->width; - av_fast_malloc(&c->slice_bits, &c->slice_bits_size, - max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE); + if (!c->pack) { + av_fast_malloc(&c->slice_bits, &c->slice_bits_size, + max_slice_size + AV_INPUT_BUFFER_PADDING_SIZE); - if (!c->slice_bits) { - av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); - return AVERROR(ENOMEM); + if (!c->slice_bits) { + av_log(avctx, AV_LOG_ERROR, "Cannot allocate temporary buffer\n"); + return AVERROR(ENOMEM); + } } switch (c->avctx->pix_fmt) { @@ -819,37 +898,6 @@ static av_cold int decode_init(AVCodecContext *avctx) ff_bswapdsp_init(&c->bdsp); ff_llviddsp_init(&c->llviddsp); - if (avctx->extradata_size >= 16) { - av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", - avctx->extradata[3], avctx->extradata[2], - avctx->extradata[1], avctx->extradata[0]); - av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", - AV_RB32(avctx->extradata + 4)); - c->frame_info_size = AV_RL32(avctx->extradata + 8); - c->flags = AV_RL32(avctx->extradata + 12); - - if (c->frame_info_size != 4) - avpriv_request_sample(avctx, "Frame info not 4 bytes"); - av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags); - c->slices = (c->flags >> 24) + 1; - c->compression = c->flags & 1; - c->interlaced = c->flags & 0x800; - } else if (avctx->extradata_size == 8) { - av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", - avctx->extradata[3], avctx->extradata[2], - avctx->extradata[1], avctx->extradata[0]); - av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", - AV_RB32(avctx->extradata + 4)); - c->interlaced = 0; - c->pro = 1; - c->frame_info_size = 4; - } else { - av_log(avctx, AV_LOG_ERROR, - "Insufficient extradata size %d, should be at least 16\n", - avctx->extradata_size); - return AVERROR_INVALIDDATA; - } - c->slice_bits_size = 0; switch (avctx->codec_tag) { @@ -903,12 +951,87 @@ static av_cold int decode_init(AVCodecContext *avctx) avctx->pix_fmt = AV_PIX_FMT_YUV444P; avctx->colorspace = AVCOL_SPC_BT709; break; + case MKTAG('U', 'M', 'Y', '2'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + avctx->colorspace = AVCOL_SPC_BT470BG; + break; + case MKTAG('U', 'M', 'H', '2'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV422P; + avctx->colorspace = AVCOL_SPC_BT709; + break; + case MKTAG('U', 'M', 'Y', '4'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + avctx->colorspace = AVCOL_SPC_BT470BG; + break; + case MKTAG('U', 'M', 'H', '4'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_YUV444P; + avctx->colorspace = AVCOL_SPC_BT709; + break; + case MKTAG('U', 'M', 'R', 'G'): + c->planes = 3; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_GBRP; + break; + case MKTAG('U', 'M', 'R', 'A'): + c->planes = 4; + c->pack = 1; + avctx->pix_fmt = AV_PIX_FMT_GBRAP; + break; default: av_log(avctx, AV_LOG_ERROR, "Unknown Ut Video FOURCC provided (%08X)\n", avctx->codec_tag); return AVERROR_INVALIDDATA; } + if (c->pack && avctx->extradata_size >= 16) { + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", + AV_RB32(avctx->extradata + 4)); + c->compression = avctx->extradata[8]; + if (c->compression != 2) + avpriv_request_sample(avctx, "Unknown compression type"); + c->slices = avctx->extradata[9] + 1; + } else if (avctx->extradata_size >= 16) { + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", + AV_RB32(avctx->extradata + 4)); + c->frame_info_size = AV_RL32(avctx->extradata + 8); + c->flags = AV_RL32(avctx->extradata + 12); + + if (c->frame_info_size != 4) + avpriv_request_sample(avctx, "Frame info not 4 bytes"); + av_log(avctx, AV_LOG_DEBUG, "Encoding parameters %08"PRIX32"\n", c->flags); + c->slices = (c->flags >> 24) + 1; + c->compression = c->flags & 1; + c->interlaced = c->flags & 0x800; + } else if (avctx->extradata_size == 8) { + av_log(avctx, AV_LOG_DEBUG, "Encoder version %d.%d.%d.%d\n", + avctx->extradata[3], avctx->extradata[2], + avctx->extradata[1], avctx->extradata[0]); + av_log(avctx, AV_LOG_DEBUG, "Original format %"PRIX32"\n", + AV_RB32(avctx->extradata + 4)); + c->interlaced = 0; + c->pro = 1; + c->frame_info_size = 4; + } else { + av_log(avctx, AV_LOG_ERROR, + "Insufficient extradata size %d, should be at least 16\n", + avctx->extradata_size); + return AVERROR_INVALIDDATA; + } + return 0; } diff --git a/libavformat/riff.c b/libavformat/riff.c index 3f0b390774..89117250d4 100644 --- a/libavformat/riff.c +++ b/libavformat/riff.c @@ -404,6 +404,12 @@ const AVCodecTag ff_codec_bmp_tags[] = { { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'Y', '2') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'A') }, { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'Q', 'R', 'G') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'Y', '2') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'H', '2') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'Y', '4') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'H', '4') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'R', 'A') }, + { AV_CODEC_ID_UTVIDEO, MKTAG('U', 'M', 'R', 'G') }, { AV_CODEC_ID_VBLE, MKTAG('V', 'B', 'L', 'E') }, { AV_CODEC_ID_ESCAPE130, MKTAG('E', '1', '3', '0') }, { AV_CODEC_ID_DXTORY, MKTAG('x', 't', 'o', 'r') },