From patchwork Fri Aug 11 09:10:46 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alexander Bilyak X-Patchwork-Id: 4688 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.46.211 with SMTP id u202csp574957vsu; Fri, 11 Aug 2017 02:11:47 -0700 (PDT) X-Received: by 10.28.69.197 with SMTP id l66mr8650905wmi.140.1502442707768; Fri, 11 Aug 2017 02:11:47 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502442707; cv=none; d=google.com; s=arc-20160816; b=dly3a/A7pwxoQu6ClrSP6zGJPPlxO7R0AFR+hkEXVujGSCnpheI/+TfPFdVPZU8dKp 3YELUfNUvyGlOYxSTxHi2G/fZKfVYl0HuQHZ1CIHnqqNLq7CnErC0KftVd6neD1XdLLY i5GySBxMZRdB4GnBu9RNbseZc7LO2eRkkCTIJxaBUslYQfywLggYkot7rwXgjJZmZmww DHbD50wiTn7p8us6lrmQtMvei++rrUvSxwrDsW8iKBUieot+V/77AUhi6Uo/1x+W1rHu jHR8QEXyhyVN2vr3CWZQIK4ygcWlW3uDTEOeEnAPSrPI1XhRIGZKFa8+RXxX+9sCC4/c gCdg== 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:dkim-signature:delivered-to:arc-authentication-results; bh=XwoaZXqmWevkkWzdDFsAIFwNRn6pkrZb/gppHJ7yn1Y=; b=t6KIbYKv9Vs1bLipXVJRr/rK2cpteNaFnuP0S4qzaeEKqdwrY6i69tR9tbrEys49r3 HBMpnofB2me0Z/TZ2IXmxf5QcIfKbgOrXNVKmKPY4NRFPjlAzyLKLDiE0Dp4gDpA/2nD KnGmoaKgtovW/hQ7vZnZVbGAOUf8F3mWOzhcVvwHK4yQgpVhlQxKqNoPeYoeC3z2p4yY hz80tFpg3jrmM7/HlzpXaqJGHsW3EOecqMHhE3Hqc/wLuj88vzPQ7hibPmvREJCLh8sq gKHyT2Gy1ignuWdEc22JGhf+TKIXCy0mQJWdpnuPmYVrzvgqrKnLE1q+W5iEfdBbbThX 3QJA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=gwkncyu8; 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 l21si461039wmb.118.2017.08.11.02.11.47; Fri, 11 Aug 2017 02:11:47 -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=gwkncyu8; 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 E8538689CDD; Fri, 11 Aug 2017 12:11:41 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr0-f195.google.com (mail-wr0-f195.google.com [209.85.128.195]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id F3B44689B11 for ; Fri, 11 Aug 2017 12:11:34 +0300 (EEST) Received: by mail-wr0-f195.google.com with SMTP id c24so2135880wra.2 for ; Fri, 11 Aug 2017 02:11:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Y/xb11RsQXFHP3dSZWZ4H6rtmbFf9d+jy4yFwYHM5fM=; b=gwkncyu8aEhMmnReD8h7ajMu0GfGEMUuZoEI2YwunH++makuK3Wl1qeA4QafNhK+fG mhiwU0B26qDEQQDLpJhTOEC03uzCnLXWVeolH78cJvtdlv45DxxQTg3dskv+fG+Gdkzv 1Hz+mZc3JcuSQIGMg2djOQWm9znxtUkIQKE0HfBg9atpU3NnIUwrRh24v8PvnvxMlAho ZfH0ORtUbPEiQ/IFWam/ggg1A0qYQWxxh5MjsSlw5C5c6hvxuF30hz0kuBIU0U1VnS+m u3xjbvCHz9JcleWBWSVWhvhQ2z70EYfLBrT+xSRhTpZ1hGtyMW8ixURgub31r2e8xVEi SmDA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Y/xb11RsQXFHP3dSZWZ4H6rtmbFf9d+jy4yFwYHM5fM=; b=oqu+m3m2u964CjN93mH9XvDoF6h/umUDeD69b211CpIAAlEzKXhnbtMvWRfVvOv2SF sorU1pmWDZEB7Uc4vETZtxgiOAOk/9kA8rtYJ+EIKLCKyi3sNYDfQpDolhoD2DOdy/YK arHHEQlvwmlrNtHk2XzXHCb8Xt4XCNAs3eUcwtuuEdwsAhmtasufb7q85eXNIrPDPpRW +WoW1g1pI+JnOjHKSxdmmbFPpgz9wEesZ9xK11z7NntZvLX7yaS7VRHZlfmcP2AjYLOY ARbWMPnhYqgjFZWSZLGkHCIM8ONFpmvlIU3KFT0RmHhtJqrp58cyrDUHaBxk5q619ACr DqHw== X-Gm-Message-State: AHYfb5jDQkSV6lhgrtp+1mPnNI3OgCyE01mZTfrJolSo89dlx6IXQynq ttgnHTBnhaoubsR+Xq0= X-Received: by 10.223.128.46 with SMTP id 43mr11392167wrk.246.1502442696881; Fri, 11 Aug 2017 02:11:36 -0700 (PDT) Received: from plumbum.astim.local (host113-234-static.10-188-b.business.telecomitalia.it. [188.10.234.113]) by smtp.googlemail.com with ESMTPSA id x4sm918321wma.33.2017.08.11.02.11.22 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 11 Aug 2017 02:11:22 -0700 (PDT) From: Alexander Bilyak To: ffmpeg-devel@ffmpeg.org Date: Fri, 11 Aug 2017 11:10:46 +0200 Message-Id: <20170811091046.1094-2-bilyak.alexander@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170811091046.1094-1-bilyak.alexander@gmail.com> References: <20170811091046.1094-1-bilyak.alexander@gmail.com> Subject: [FFmpeg-devel] [PATCH 2/2] libavdevice: Add SQV screen capture device 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: Alexander Bilyak MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" For making it more reasonable QSV screen capture is added to device list, so it can be read as usual device, producing packets to its output. Nevertheless it is only wrapper around QSV decoder with screen capture plugin loading --- configure | 2 + libavdevice/Makefile | 1 + libavdevice/alldevices.c | 1 + libavdevice/qsvscreen.c | 216 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 220 insertions(+) create mode 100644 libavdevice/qsvscreen.c diff --git a/configure b/configure index 942765e8a3..c5119cf672 100755 --- a/configure +++ b/configure @@ -3035,6 +3035,8 @@ oss_indev_deps_any="soundcard_h sys_soundcard_h" oss_outdev_deps_any="soundcard_h sys_soundcard_h" pulse_indev_deps="libpulse" pulse_outdev_deps="libpulse" +screen_qsv_indev_deps="libmfx" +screen_qsv_indev_select="screen_qsv_decoder" qtkit_indev_extralibs="-framework QTKit -framework Foundation -framework QuartzCore" qtkit_indev_select="qtkit" sdl2_outdev_deps="sdl2" diff --git a/libavdevice/Makefile b/libavdevice/Makefile index c055d6718d..327cbb0a6c 100644 --- a/libavdevice/Makefile +++ b/libavdevice/Makefile @@ -38,6 +38,7 @@ OBJS-$(CONFIG_PULSE_INDEV) += pulse_audio_dec.o \ pulse_audio_common.o timefilter.o OBJS-$(CONFIG_PULSE_OUTDEV) += pulse_audio_enc.o \ pulse_audio_common.o +OBJS-$(CONFIG_SCREEN_QSV_INDEV) += qsvscreen.o OBJS-$(CONFIG_QTKIT_INDEV) += qtkit.o OBJS-$(CONFIG_SDL2_OUTDEV) += sdl2.o OBJS-$(CONFIG_SNDIO_INDEV) += sndio_dec.o sndio.o diff --git a/libavdevice/alldevices.c b/libavdevice/alldevices.c index a8ed53ae5d..bcc46c2691 100644 --- a/libavdevice/alldevices.c +++ b/libavdevice/alldevices.c @@ -57,6 +57,7 @@ static void register_all(void) REGISTER_OUTDEV (OPENGL, opengl); REGISTER_INOUTDEV(OSS, oss); REGISTER_INOUTDEV(PULSE, pulse); + REGISTER_INDEV (SCREEN_QSV, screen_qsv); REGISTER_INDEV (QTKIT, qtkit); REGISTER_OUTDEV (SDL2, sdl2); REGISTER_INOUTDEV(SNDIO, sndio); diff --git a/libavdevice/qsvscreen.c b/libavdevice/qsvscreen.c new file mode 100644 index 0000000000..475a9a4c50 --- /dev/null +++ b/libavdevice/qsvscreen.c @@ -0,0 +1,216 @@ +/* + * Intel QSV screen capture interface + * + * This file is part of FFmpeg. + * + * Copyright (C) 2017 Alexander Bilyak + * + * FFmpeg is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public License + * as published by the Free Software Foundation; either version 2.1 + * of the License, or (at your option) any later version. + * + * FFmpeg is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file + * Intel QSV Screen capture demuxer interface + * @author Alexander Bilyak + * @note As Intel Media SDK provide screen capture as plug-in to QSV decoder + * so this "device" is nothing more than wrapper around QSV decoder + * with appropiate settings. + */ + +#include "config.h" +#include "libavformat/internal.h" +#include "libavutil/opt.h" +#include "libavcodec/avcodec.h" +#include "libavutil/time.h" +#include "libavutil/imgutils.h" + +/** + * QSV screen capture context + */ +typedef struct QSVScreenContext { + + const AVClass *class; /**< Class for private options */ + + AVCodecContext *avctx; /**< Codec context used for fake decoding */ + AVCodec *codec; /**< Codec used for fake decoding */ + + int draw_mouse; /**< Draw mouse cursor (private option) */ + int width; /**< Width of the grab frame (private option) */ + int height; /**< Height of the grab frame (private option) */ +} QSVScreenContext; + +/** + * Initializes the QSV screen device demuxer (public device demuxer API). + * + * @param avctx Context from avformat core + * + * @return 0 on success, a negative AVERROR on error + */ +static int screen_qsv_read_header(AVFormatContext *avctx) +{ + int ret; + AVStream *st; + QSVScreenContext *ctx = avctx->priv_data; + AVDictionary* opts = NULL; + + ctx->codec = avcodec_find_decoder_by_name("screen_qsv"); + if (!ctx->codec) { + ret = AVERROR_DECODER_NOT_FOUND; + goto error; + } + + ctx->avctx = avcodec_alloc_context3(ctx->codec); + if (!ctx->avctx) { + ret = AVERROR(ENOMEM); + goto error; + } + + ctx->avctx->width = ctx->width; + ctx->avctx->height = ctx->height; + + av_dict_set_int(&opts, "draw_mouse", ctx->draw_mouse, 0 ); + + ret = avcodec_open2(ctx->avctx, ctx->codec, &opts); + if (ret) + goto error; + + st = avformat_new_stream(avctx, NULL); + if (!st) { + ret = AVERROR(ENOMEM); + goto error; + } + avpriv_set_pts_info(st, 96, 1, 1000000); /* 96 bits pts in microseconds */ + + st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; + st->codecpar->codec_id = AV_CODEC_ID_RAWVIDEO; + st->codecpar->codec_tag = MKTAG('N', 'V', '1', '2'); + st->codecpar->width = ctx->width; + st->codecpar->height = ctx->height; + st->codecpar->format = AV_PIX_FMT_NV12; + st->codecpar->bit_rate = st->codecpar->width * st->codecpar->height * 12; + + ret = avcodec_send_packet(ctx->avctx, NULL); + if (ret) + goto error; + + return 0; + +error: + if (ctx->avctx) + avcodec_free_context(&ctx->avctx); + + return ret; +} + +/** + * Grabs a frame from QSV screen device (public device demuxer API). + * + * @param avctx Context from avformat core + * + * @param pkt Packet holding the grabbed frame + * + * @return frame size in bytes, a negative AVERROR on error. + */ +static int screen_qsv_read_packet(AVFormatContext *avctx, AVPacket *pkt) +{ + QSVScreenContext *ctx = avctx->priv_data; + int ret; + + int size = ctx->width * ctx->height * 12/8; + + AVFrame *frame = av_frame_alloc(); + if (!frame) + return AVERROR(ENOMEM); + + frame->format = AV_PIX_FMT_NV12; + frame->width = ctx->width; + frame->height = ctx->height; + + ret = av_frame_get_buffer(frame, 32); + if (ret < 0) + goto error; + + ret = avcodec_receive_frame(ctx->avctx, frame); + if (ret < 0) + goto error; + + ret = av_new_packet(pkt, size); + if (ret < 0) + goto error; + + ret = av_image_copy_to_buffer(pkt->data, size, (const uint8_t **)frame->data, + frame->linesize, frame->format, frame->width, frame->height, 1); + if (ret < 0) + goto error; + + pkt->stream_index = 0; + pkt->pts = av_gettime(); + pkt->pos = frame->pkt_pos; + pkt->size = size; + + av_frame_free(&frame); + + return size; +error: + if (frame) { + av_frame_free(&frame); + } + + return ret; +} + +/** + * Closes QSV screen device frame grabber (public device demuxer API). + * + * @param avctx Context from avformat core + * + * @return 0 on success, a negative AVERROR on error + */ +static int screen_qsv_read_close(AVFormatContext *avctx) +{ + QSVScreenContext *ctx = avctx->priv_data; + + if (ctx->avctx) + avcodec_free_context(&ctx->avctx); + + return 0; +} + +#define OFFSET(x) offsetof(struct QSVScreenContext, x) +#define DEC AV_OPT_FLAG_DECODING_PARAM +static const AVOption options[] = { + { "draw_mouse", "draw the mouse pointer", OFFSET(draw_mouse), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, DEC }, + { "video_size", "set video frame size", OFFSET(width), AV_OPT_TYPE_IMAGE_SIZE, {.str = NULL}, 0, 0, DEC }, + { NULL }, +}; + +static const AVClass screen_qsv_class = { + .class_name = "QSVScreen indev", + .item_name = av_default_item_name, + .option = options, + .version = LIBAVUTIL_VERSION_INT, +}; + +/** QSV Screen frame grabber device demuxer declaration */ +AVInputFormat ff_screen_qsv_demuxer = { + .name = "screen_qsv", + .long_name = NULL_IF_CONFIG_SMALL("Intel QSV screen capture"), + .priv_data_size = sizeof(QSVScreenContext), + .read_header = screen_qsv_read_header, + .read_packet = screen_qsv_read_packet, + .read_close = screen_qsv_read_close, + .flags = AVFMT_NOFILE, + .priv_class = &screen_qsv_class, +};