From patchwork Tue Apr 10 21:21:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Patrick Keroulas X-Patchwork-Id: 8386 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.1.70 with SMTP id c67csp78776jad; Tue, 10 Apr 2018 16:47:40 -0700 (PDT) X-Google-Smtp-Source: AIpwx48iLd4YzTad30FQPPBjxS+f36HPkUHkcoPppgmi0kj861gIZtQgx6xhhT2DHE6ECOF/omx4 X-Received: by 10.28.184.21 with SMTP id i21mr979468wmf.94.1523404060854; Tue, 10 Apr 2018 16:47:40 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1523404060; cv=none; d=google.com; s=arc-20160816; b=MTWUaTM6vUki72xbgW91IUqtYyxn1xoV8r0nHp35foQjUF/En2Wkb/+Ay+FcZ+cDG2 bZe9SGgKXUdpRSNdJJUEQKA4yNri7+M4b3BkI/8YWJ/Ua+1yAK52qqPfU4R8KuvbbKt3 Jc0NJm5DjaCn5XPh3e7kirklhYcp5jRnGYchIXQG0ERvF3P/oXJH+2jTqWxWMqx2Zpds ssE53N5TzsDtg+A+VMPey89K42/tUHEj3S3V6R7O8E6jDeOH1O8luW9rc1pdbJwT0B8t B2MvXPwTQ86opWEoB3zUT6hc70mthzdVp8dKqkAwNUBB4ctc0FqTvNYNpwAyFyQKPCYJ CuVQ== 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:cc: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:delivered-to:arc-authentication-results; bh=JVRe9ZZTvYg3zQKBPG+FOh1h+oYrDZbGBTeiEI1sQDg=; b=zKdjkxPFXoXnkMNe1SXo0Brc2axMzKTajLIkJX6LXQrCNXRCFPG8Q2wFUwY4N8fP99 Jy/Bel1fmi8Xf2Onb579g/IRUo9gaRvE1BZtzEKOXTve17y533s4rlKEKTJxOI1EbIwr POwVgyUPunFlUJbp8eXrdCkP2mKM0FUvSzfiyq+g/Mn5TTrEn8bPF1UsM7JlR0IVYeBN m35dCgmitAcq3WEYvBpm0UJqSJMo+oCTttdIu/m1gNspA8NBCcaOgsyrj+UD6wjr0rUY M4SrLU7rYANge8GmZw/UPsYa+vrWg5mw3LAZ+xG+LeHG6uwHhgQiRrS42QDe6qIzL40Z Skkw== ARC-Authentication-Results: i=1; mx.google.com; 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 Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id a22si72009wmg.143.2018.04.10.16.47.40; Tue, 10 Apr 2018 16:47:40 -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; 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 Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id EF01968A1BE; Wed, 11 Apr 2018 02:46:54 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail.savoirfairelinux.com (mail.savoirfairelinux.com [208.88.110.44]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 33BA068A0B2 for ; Wed, 11 Apr 2018 00:21:20 +0300 (EEST) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id 8680E9C3343 for ; Tue, 10 Apr 2018 17:21:42 -0400 (EDT) Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavisd-new, port 10032) with ESMTP id DsL7gnDEWMxE; Tue, 10 Apr 2018 17:21:41 -0400 (EDT) Received: from localhost (localhost [127.0.0.1]) by mail.savoirfairelinux.com (Postfix) with ESMTP id E4B1B9C3093; Tue, 10 Apr 2018 17:21:41 -0400 (EDT) X-Virus-Scanned: amavisd-new at mail.savoirfairelinux.com Received: from mail.savoirfairelinux.com ([127.0.0.1]) by localhost (mail.savoirfairelinux.com [127.0.0.1]) (amavisd-new, port 10026) with ESMTP id sTf6o084N55a; Tue, 10 Apr 2018 17:21:41 -0400 (EDT) Received: from pkeroulas.mtl.sfl (unknown [192.168.50.171]) by mail.savoirfairelinux.com (Postfix) with ESMTPSA id B920A9C3343; Tue, 10 Apr 2018 17:21:41 -0400 (EDT) From: Patrick Keroulas To: ffmpeg-devel@ffmpeg.org Date: Tue, 10 Apr 2018 17:21:36 -0400 Message-Id: <1523395297-13466-2-git-send-email-patrick.keroulas@savoirfairelinux.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1523395297-13466-1-git-send-email-patrick.keroulas@savoirfairelinux.com> References: <1523395297-13466-1-git-send-email-patrick.keroulas@savoirfairelinux.com> X-Mailman-Approved-At: Wed, 11 Apr 2018 02:46:53 +0300 Subject: [FFmpeg-devel] [PATCH v1 2/3] avcodec/bitpacked: add interlace support 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 Cc: Damien Riegel , Patrick Keroulas MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Damien Riegel This codec is already capable of depacking some combinations of pixel formats and depth as defined in the RFC4175. The only difference between progressive and interlace is that either a packet will contain the whole frame, or only a field of the frame. As FFmpeg is not capable of handling fields only and recompose an interlaced frame from that, it has to be done by the codec. To achieve that, it must use two AVPacket: one for each field (top and bottom). Signed-off-by: Damien Riegel Signed-off-by: Patrick Keroulas --- libavcodec/avcodec.h | 4 +++ libavcodec/bitpacked.c | 76 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 12 deletions(-) diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h index fb0c6fa..350e8d9 100644 --- a/libavcodec/avcodec.h +++ b/libavcodec/avcodec.h @@ -1480,6 +1480,10 @@ typedef struct AVPacket { */ #define AV_PKT_FLAG_DISPOSABLE 0x0010 +/** + * The packet contains a top field. + */ +#define AV_PKT_FLAG_TOP_FIELD 0x0010 enum AVSideDataParamChangeFlags { AV_SIDE_DATA_PARAM_CHANGE_CHANNEL_COUNT = 0x0001, diff --git a/libavcodec/bitpacked.c b/libavcodec/bitpacked.c index 85d4bdd..d81703d 100644 --- a/libavcodec/bitpacked.c +++ b/libavcodec/bitpacked.c @@ -33,15 +33,19 @@ struct BitpackedContext { int (*decode)(AVCodecContext *avctx, AVFrame *frame, - AVPacket *pkt); + AVPacket *pkt, int top_field); + AVPacket *first_field_pkt; }; /* For this format, it's a simple passthrough */ static int bitpacked_decode_uyvy422(AVCodecContext *avctx, AVFrame *frame, - AVPacket *avpkt) + AVPacket *avpkt, int top_field) { int ret; + if (frame->interlaced_frame) + return AVERROR_PATCHWELCOME; + /* there is no need to copy as the data already match * a known pixel format */ frame->buf[0] = av_buffer_ref(avpkt->buf); @@ -56,17 +60,22 @@ static int bitpacked_decode_uyvy422(AVCodecContext *avctx, AVFrame *frame, } static int bitpacked_decode_yuv422p10(AVCodecContext *avctx, AVFrame *frame, - AVPacket *avpkt) + AVPacket *avpkt, int top_field) { uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 20; uint64_t packet_size = (uint64_t)avpkt->size * 8; + int interlaced = frame->interlaced_frame; GetBitContext bc; uint16_t *y, *u, *v; int ret, i, j; - - if (frame_size > packet_size) + /* check packet size depending on the interlaced/progressive format */ + if (interlaced) { + if ((frame_size >> 1) > packet_size) + return AVERROR_INVALIDDATA; + } else if (frame_size > packet_size) { return AVERROR_INVALIDDATA; + } if (avctx->width % 2) return AVERROR_PATCHWELCOME; @@ -75,7 +84,18 @@ static int bitpacked_decode_yuv422p10(AVCodecContext *avctx, AVFrame *frame, if (ret) return ret; - for (i = 0; i < avctx->height; i++) { + /* + * if the frame is interlaced, the avpkt we are getting is either the top + * or the bottom field. If it's the bottom field, it contains all the odd + * lines of the recomposed frame, so we start at offset 1. + */ + i = (interlaced && !top_field) ? 1 : 0; + + /* + * Packets from interlaced frames contain either even lines, or odd + * lines, so increment by two in that case. + */ + for (; i < avctx->height; interlaced ? i += 2 : i++) { y = (uint16_t*)(frame->data[0] + i * frame->linesize[0]); u = (uint16_t*)(frame->data[1] + i * frame->linesize[1]); v = (uint16_t*)(frame->data[2] + i * frame->linesize[2]); @@ -100,13 +120,20 @@ static av_cold int bitpacked_init_decoder(AVCodecContext *avctx) if (avctx->codec_tag == MKTAG('U', 'Y', 'V', 'Y')) { if (avctx->bits_per_coded_sample == 16 && - avctx->pix_fmt == AV_PIX_FMT_UYVY422) + avctx->pix_fmt == AV_PIX_FMT_UYVY422) { + + if (avctx->field_order > AV_FIELD_PROGRESSIVE) { + av_log(avctx, AV_LOG_ERROR, "interlaced not yet supported for 8-bit\n"); + return AVERROR_PATCHWELCOME; + } + bc->decode = bitpacked_decode_uyvy422; - else if (avctx->bits_per_coded_sample == 20 && - avctx->pix_fmt == AV_PIX_FMT_YUV422P10) + } else if (avctx->bits_per_coded_sample == 20 && + avctx->pix_fmt == AV_PIX_FMT_YUV422P10) { bc->decode = bitpacked_decode_yuv422p10; - else + } else { return AVERROR_INVALIDDATA; + } } else { return AVERROR_INVALIDDATA; } @@ -120,24 +147,49 @@ static int bitpacked_decode(AVCodecContext *avctx, void *data, int *got_frame, struct BitpackedContext *bc = avctx->priv_data; int buf_size = avpkt->size; AVFrame *frame = data; + int top_field = 0; int res; frame->pict_type = AV_PICTURE_TYPE_I; frame->key_frame = 1; + if (avctx->field_order != AV_FIELD_PROGRESSIVE) { + top_field = avpkt->flags & AV_PKT_FLAG_TOP_FIELD; + frame->interlaced_frame = 1; + frame->top_field_first = 1; + } + if (avctx->pix_fmt == AV_PIX_FMT_YUV422P10) { res = ff_get_buffer(avctx, frame, 0); if (res < 0) return res; } - res = bc->decode(avctx, frame, avpkt); + if (frame->interlaced_frame) { + + if (top_field) { + bc->first_field_pkt = av_packet_clone(avpkt); + return 0; + + } else if (bc->first_field_pkt) { + /* Combine the 2 fields in a single frame. + * N fields/s give N/2 frames/s. */ + res = bc->decode(avctx, frame, bc->first_field_pkt, 1); + res += bc->decode(avctx, frame, avpkt, 0); + + av_packet_free(&bc->first_field_pkt); + } else { + return 0; + } + } else { + res = bc->decode(avctx, frame, avpkt, 0); + } + if (res) return res; *got_frame = 1; return buf_size; - } AVCodec ff_bitpacked_decoder = {