From patchwork Fri Oct 6 12:55:44 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Devin Heitmueller X-Patchwork-Id: 5437 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.2.161.90 with SMTP id m26csp427687jah; Fri, 6 Oct 2017 05:56:23 -0700 (PDT) X-Google-Smtp-Source: AOwi7QD4zy5GrxornzDjnPoTQqZoboepzOW9UMAlQNetq4XUGidsa/67I4WrkaD+VqmaQE5BZsZX X-Received: by 10.223.151.51 with SMTP id r48mr2029876wrb.164.1507294583002; Fri, 06 Oct 2017 05:56:23 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1507294582; cv=none; d=google.com; s=arc-20160816; b=GV7D1atIN87RmFyfCvEDLOo1KYMVsosv6gN57ITV5qQyoMZw4sfbnjdf3P1kvvMPTV qTkmBymNB5KmlQzZs2r4iRfrMd1HZeYnIZojKL2MEPTtmrt0L9xQaFVfkW63CoDJZZbv OIG/NH/0krF2yo5Gmo5cYdYLHhh/9wzRVPZpvN4UJWTtUHcW/8ZogLF99djvqsA2M/Yz 0aBpxBzpemiTDNAAbT+6rMoWX9ujAX3i9ZvGLneAXY1Nf10Fmwv9KKw6dsuotTKQOeR3 fOMPa7UxzUd39+JHprHqz2jl1H5Pknp5cxVOfJL8OfjcvdAd5OGYLxq7gyTI+vfbK0Cq u2Rg== 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=1Kuvbb+LQQpm2w/d2hCrFrAaad3WFeOSTmN/+e0C6YA=; b=hPL5GS6JTI7lLZnvnPF6oBvi3oyg5k2gnoSuNhsqRuJ3RSee6G4Wp5hB80IhWBr9/5 0FG1GWwJPgKMIokm0xF+HFa0h2yru8YiAEzKW2rAfOjRvNBRJ6gWru5yA8EQzZEubSJa M3+DcHjsnwd2ft7WrXx5XnQdnBHaRgMtBLbai9EfKkUs3iNUnMHJkLvL5h1nLC4NGkPq a14WRSHHNrcN+rOFv29//3VjSwMdaBl2E+/bMnQTK1+YDkkeh7gfdRdwtdLjFZqDGEMX QUQR90mo8Ciennc1uluWYA3KmWzsRcB6snNpiOvTqDjrTc/+DVRWxFiDj8pGWCUBXW/W Qmww== 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 o95si1252963wrb.226.2017.10.06.05.56.22; Fri, 06 Oct 2017 05:56: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; 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 1DD7A68A4D0; Fri, 6 Oct 2017 15:56:05 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from was-smtp1.livetimenet.net (50-206-97-56-static.hfc.comcastbusiness.net [50.206.97.56]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 376AC68A4B1 for ; Fri, 6 Oct 2017 15:55:57 +0300 (EEST) Received: by was-smtp1.livetimenet.net with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.84_2) (envelope-from ) id 1e0SAW-0005Xp-Ba; Fri, 06 Oct 2017 08:55:57 -0400 From: Devin Heitmueller To: ffmpeg-devel@ffmpeg.org Date: Fri, 6 Oct 2017 08:55:44 -0400 Message-Id: <20171006125544.35881-3-dheitmueller@ltnglobal.com> X-Mailer: git-send-email 2.13.2 In-Reply-To: <20171006125544.35881-1-dheitmueller@ltnglobal.com> References: <20171006125544.35881-1-dheitmueller@ltnglobal.com> X-Spam-Score: -1.9 (-) Subject: [FFmpeg-devel] [PATCHv3 2/2] libavdevice/decklink: add support for 10-bit output for Decklink SDI 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: jgreen@ltnglobal.com, Devin Heitmueller MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Can be tested via the following command: ./ffmpeg -i foo.ts -f decklink -vcodec v210 'DeckLink Duo (1)' Note that the 8-bit support works as it did before, and setting the pix_fmt isn't required for 10-bit mode. The code defaults to operating in 8-bit mode when no vcodec is specified, for backward compatibility. Updated to reflect feedback from Marton Balint Signed-off-by: Devin Heitmueller --- libavdevice/decklink_enc.cpp | 112 ++++++++++++++++++++++++++++++++----------- 1 file changed, 83 insertions(+), 29 deletions(-) diff --git a/libavdevice/decklink_enc.cpp b/libavdevice/decklink_enc.cpp index 0776741812..81df563b3b 100644 --- a/libavdevice/decklink_enc.cpp +++ b/libavdevice/decklink_enc.cpp @@ -44,20 +44,45 @@ extern "C" { class decklink_frame : public IDeckLinkVideoFrame { public: - decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe) : - _ctx(ctx), _avframe(avframe), _refs(1) { } - - virtual long STDMETHODCALLTYPE GetWidth (void) { return _avframe->width; } - virtual long STDMETHODCALLTYPE GetHeight (void) { return _avframe->height; } - virtual long STDMETHODCALLTYPE GetRowBytes (void) { return _avframe->linesize[0] < 0 ? -_avframe->linesize[0] : _avframe->linesize[0]; } - virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat(void) { return bmdFormat8BitYUV; } - virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) { return _avframe->linesize[0] < 0 ? bmdFrameFlagFlipVertical : bmdFrameFlagDefault; } - virtual HRESULT STDMETHODCALLTYPE GetBytes (void **buffer) + decklink_frame(struct decklink_ctx *ctx, AVFrame *avframe, AVCodecID codec_id, int height, int width) : + _ctx(ctx), _avframe(avframe), _avpacket(NULL), _codec_id(codec_id), _height(height), _width(width), _refs(1) { } + decklink_frame(struct decklink_ctx *ctx, AVPacket *avpacket, AVCodecID codec_id, int height, int width) : + _ctx(ctx), _avframe(NULL), _avpacket(avpacket), _codec_id(codec_id), _height(height), _width(width), _refs(1) { } + + virtual long STDMETHODCALLTYPE GetWidth (void) { return _width; } + virtual long STDMETHODCALLTYPE GetHeight (void) { return _height; } + virtual long STDMETHODCALLTYPE GetRowBytes (void) + { + if (_codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) + return _avframe->linesize[0] < 0 ? -_avframe->linesize[0] : _avframe->linesize[0]; + else + return ((GetWidth() + 47) / 48) * 128; + } + virtual BMDPixelFormat STDMETHODCALLTYPE GetPixelFormat(void) { - if (_avframe->linesize[0] < 0) - *buffer = (void *)(_avframe->data[0] + _avframe->linesize[0] * (_avframe->height - 1)); + if (_codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) + return bmdFormat8BitYUV; else - *buffer = (void *)(_avframe->data[0]); + return bmdFormat10BitYUV; + } + virtual BMDFrameFlags STDMETHODCALLTYPE GetFlags (void) + { + if (_codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) + return _avframe->linesize[0] < 0 ? bmdFrameFlagFlipVertical : bmdFrameFlagDefault; + else + return bmdFrameFlagDefault; + } + + virtual HRESULT STDMETHODCALLTYPE GetBytes (void **buffer) + { + if (_codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) { + if (_avframe->linesize[0] < 0) + *buffer = (void *)(_avframe->data[0] + _avframe->linesize[0] * (_avframe->height - 1)); + else + *buffer = (void *)(_avframe->data[0]); + } else { + *buffer = (void *)(_avpacket->data); + } return S_OK; } @@ -71,6 +96,7 @@ public: int ret = --_refs; if (!ret) { av_frame_free(&_avframe); + av_packet_free(&_avpacket); delete this; } return ret; @@ -78,6 +104,10 @@ public: struct decklink_ctx *_ctx; AVFrame *_avframe; + AVPacket *_avpacket; + AVCodecID _codec_id; + int _height; + int _width; private: std::atomic _refs; @@ -90,9 +120,11 @@ public: { decklink_frame *frame = static_cast(_frame); struct decklink_ctx *ctx = frame->_ctx; - AVFrame *avframe = frame->_avframe; - av_frame_unref(avframe); + if (frame->_avframe) + av_frame_unref(frame->_avframe); + if (frame->_avpacket) + av_packet_unref(frame->_avpacket); pthread_mutex_lock(&ctx->mutex); ctx->frames_buffer_available_spots++; @@ -118,11 +150,18 @@ static int decklink_setup_video(AVFormatContext *avctx, AVStream *st) return -1; } - if (c->format != AV_PIX_FMT_UYVY422) { - av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format!" - " Only AV_PIX_FMT_UYVY422 is supported.\n"); + if (c->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) { + if (c->format != AV_PIX_FMT_UYVY422) { + av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format!" + " Only AV_PIX_FMT_UYVY422 is supported.\n"); + return -1; + } + } else if (c->codec_id != AV_CODEC_ID_V210) { + av_log(avctx, AV_LOG_ERROR, "Unsupported codec type!" + " Only V210 and wrapped frame with AV_PIX_FMT_UYVY422 are supported.\n"); return -1; } + if (ff_decklink_set_format(avctx, c->width, c->height, st->time_base.num, st->time_base.den, c->field_order)) { av_log(avctx, AV_LOG_ERROR, "Unsupported video size, framerate or field order!" @@ -230,27 +269,42 @@ static int decklink_write_video_packet(AVFormatContext *avctx, AVPacket *pkt) { struct decklink_cctx *cctx = (struct decklink_cctx *)avctx->priv_data; struct decklink_ctx *ctx = (struct decklink_ctx *)cctx->ctx; - AVFrame *avframe, *tmp = (AVFrame *)pkt->data; + AVStream *st = avctx->streams[pkt->stream_index]; + AVFrame *avframe = NULL, *tmp = (AVFrame *)pkt->data; + AVPacket *avpacket = NULL; decklink_frame *frame; buffercount_type buffered; HRESULT hr; - if (tmp->format != AV_PIX_FMT_UYVY422 || - tmp->width != ctx->bmd_width || - tmp->height != ctx->bmd_height) { - av_log(avctx, AV_LOG_ERROR, "Got a frame with invalid pixel format or dimension.\n"); - return AVERROR(EINVAL); - } - avframe = av_frame_clone(tmp); - if (!avframe) { - av_log(avctx, AV_LOG_ERROR, "Could not clone video frame.\n"); - return AVERROR(EIO); + if (st->codecpar->codec_id == AV_CODEC_ID_WRAPPED_AVFRAME) { + if (tmp->format != AV_PIX_FMT_UYVY422 || + tmp->width != ctx->bmd_width || + tmp->height != ctx->bmd_height) { + av_log(avctx, AV_LOG_ERROR, "Got a frame with invalid pixel format or dimension.\n"); + return AVERROR(EINVAL); + } + + avframe = av_frame_clone(tmp); + if (!avframe) { + av_log(avctx, AV_LOG_ERROR, "Could not clone video frame.\n"); + return AVERROR(EIO); + } + + frame = new decklink_frame(ctx, avframe, st->codecpar->codec_id, avframe->height, avframe->width); + } else { + avpacket = av_packet_clone(pkt); + if (!avpacket) { + av_log(avctx, AV_LOG_ERROR, "Could not clone video frame.\n"); + return AVERROR(EIO); + } + + frame = new decklink_frame(ctx, avpacket, st->codecpar->codec_id, ctx->bmd_height, ctx->bmd_width); } - frame = new decklink_frame(ctx, avframe); if (!frame) { av_log(avctx, AV_LOG_ERROR, "Could not create new frame.\n"); av_frame_free(&avframe); + av_packet_free(&avpacket); return AVERROR(EIO); }