From patchwork Mon Aug 7 06:43:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paras X-Patchwork-Id: 4647 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.46.211 with SMTP id u202csp2505328vsu; Sun, 6 Aug 2017 23:44:17 -0700 (PDT) X-Received: by 10.223.135.218 with SMTP id c26mr6717782wrc.10.1502088257190; Sun, 06 Aug 2017 23:44:17 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1502088257; cv=none; d=google.com; s=arc-20160816; b=c+q3BQV6P96/fvPBWAtNBUUQ8vZfJlGM11rXFH1UEO0EmVLU48beZGlbQuoc48eon/ yGv1HSJNybALLrQaU6+KDDoLaDJUKVgu6EQU+SL8vOC0Xu2znTuBA64cFCF9Lb0/568D EraPsJ5D5YDxEQGJBwMjA8XhXf3CrOGl3yIIHYA5c/7EDl3JNUt/ufHtI9k069ZITcl5 OmY4NrTcWqxo2SRrl3MrHv7WNbR8NibEOj93PZnPvr9QGB6Zc37RkZP8DogBEKbBAXQJ 29RTS+SeQkn8N/BgcglBWYyX0Z9h0C50EC+GB1/YMcfxtq1u+Yx+wBeEUrjcI+CUMrie IfMg== 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:message-id:date:to:from:dkim-signature :delivered-to:arc-authentication-results; bh=sQJeEbEsjjMDhf/CixedFSnjerWIApsgQ1K9x5x0boc=; b=ChUxSSTchNRomUqKKF+ZlPVkd9/ve8bL6PLW5r50PyVLBd3Z9aV4syzZ5+t8h12bxx WeFNERihIKB/pFtZN/m7Jfya/RcMExjK0rTA5AonsUY2Hx6h0bqinEzKiJs+UeDMwoj3 Mfr7fuw5ZaOMRiAOU7J7rdoC5VKhbhzrLiMjIpXr+xtEKgQEWDu9J/zWperJWXGirYHC NDUstCHM5DNZwEwL05L5RX9nyFdyG54GC2LwFqTVr5h9bCCbdJe/SGGKcGEB7KNk0a0C RIFiDWFTUpfOhdgqfLQ2nADe6ez/CXw3w7C9FRU7l6ErwGMXA0B4QXduU4hIqeGsASty EJzA== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.b=t5T/rLQ4; 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 q27si8125753wrc.492.2017.08.06.23.44.16; Sun, 06 Aug 2017 23:44:17 -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.b=t5T/rLQ4; 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 934F1680578; Mon, 7 Aug 2017 09:44:13 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf0-f195.google.com (mail-pf0-f195.google.com [209.85.192.195]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6CFCF680578 for ; Mon, 7 Aug 2017 09:44:07 +0300 (EEST) Received: by mail-pf0-f195.google.com with SMTP id t83so8164994pfj.3 for ; Sun, 06 Aug 2017 23:44:08 -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; bh=VJ6ljgMUj2uE5Hes4+c55Tal4eE35P/4oUS9hxZpRds=; b=t5T/rLQ4rAY+sSCWdPdxctUYdUMIrS0Kt/8FgJq17TyHmVmxKevFv8tjCLl3EJiOEi PIaOpe4TAMHrDNeC0iValQktbXJvJsj+94Rn0JXtI54uEPABQsWet5+qbaD3WRnMbXL6 ZQpLv3DzM3Ku2VMfdtpEOlZpunO9bU8u9aZIvM15AVEJ89CZ8dp9jktUt+y7f9jxCBWX q2Unsl/VYc9Jvnzz3Tfow9dPAsz15LIxCSGQGWH7fUWrlAA1zTtdMsROtim2Nw0GLS41 HKOt1EY+D8/17A9cNUOUzaIdiJbVwDc6iSLZ6k44O2VEj+rNS0Sw2d8OcCFnBVfNmaz+ 8AVA== 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; bh=VJ6ljgMUj2uE5Hes4+c55Tal4eE35P/4oUS9hxZpRds=; b=URtPGlKawd8H901/Iod8s46m4ote5WQNptolf2VE4LbWN1pUZQC+ACY/bjXjkP/Jea W8VgXM/HiI51BlhEfOEqepznOVVimsf7pDzrOmlZiFpXjwtieZty6+8HaAtl3do3ClIE mBnxAMrTDJt/EJ52IJg14brau/5YC0vjbuhAYPnx4mgv3DOl8PY96ogoCKE0HGLDw8j5 6obv+btnmkY9iViY622iADDSIRmwNGWIs3fz/0gLH+EEA4v4ZKo4oMOLS6ui3De66qcZ h4C5nSqCQ877P9mBzwUn1+ZrDX6o/df6vcp5LfFWbdaky5kJPS8+W0UtT6HNSwGeYJ3M JT6A== X-Gm-Message-State: AIVw110XXaEM0fxsqQjxMBcgUqrgtwDNeA9glZyUvP4ORgd38GjIK6Dk 9+fo4RVKpEUZE8ey X-Received: by 10.98.153.153 with SMTP id t25mr10844706pfk.224.1502088247140; Sun, 06 Aug 2017 23:44:07 -0700 (PDT) Received: from dhcppc9.localdomain ([210.56.106.127]) by smtp.gmail.com with ESMTPSA id m65sm12758604pfi.94.2017.08.06.23.44.05 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 06 Aug 2017 23:44:06 -0700 (PDT) From: Paras Chadha To: ffmpeg-devel@ffmpeg.org Date: Mon, 7 Aug 2017 12:13:56 +0530 Message-Id: <1502088236-22172-1-git-send-email-paraschadha18@gmail.com> X-Mailer: git-send-email 2.4.11 Subject: [FFmpeg-devel] [PATCH] Add FITS Muxer 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: Paras Chadha MIME-Version: 1.0 Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" Signed-off-by: Paras Chadha --- Added a new line in img2enc to add support for writing frames into separate FITS files in a fashion similar to gif. The following command can be used for that: ffmpeg -i INPUT -c:v fits -f image2 "out%d.fits" libavformat/Makefile | 1 + libavformat/allformats.c | 2 +- libavformat/fitsenc.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++ libavformat/img2enc.c | 2 + 4 files changed, 187 insertions(+), 1 deletion(-) create mode 100644 libavformat/fitsenc.c -- 2.4.11 diff --git a/libavformat/Makefile b/libavformat/Makefile index 266b77a..faca4a0 100644 --- a/libavformat/Makefile +++ b/libavformat/Makefile @@ -165,6 +165,7 @@ OBJS-$(CONFIG_FIFO_MUXER) += fifo.o OBJS-$(CONFIG_FILMSTRIP_DEMUXER) += filmstripdec.o OBJS-$(CONFIG_FILMSTRIP_MUXER) += filmstripenc.o OBJS-$(CONFIG_FITS_DEMUXER) += fitsdec.o +OBJS-$(CONFIG_FITS_MUXER) += fitsenc.o OBJS-$(CONFIG_FLAC_DEMUXER) += flacdec.o rawdec.o \ flac_picture.o \ oggparsevorbis.o \ diff --git a/libavformat/allformats.c b/libavformat/allformats.c index 3c12760..f3b2edb 100644 --- a/libavformat/allformats.c +++ b/libavformat/allformats.c @@ -121,7 +121,7 @@ static void register_all(void) REGISTER_MUXDEMUX(FFMETADATA, ffmetadata); REGISTER_MUXER (FIFO, fifo); REGISTER_MUXDEMUX(FILMSTRIP, filmstrip); - REGISTER_DEMUXER (FITS, fits); + REGISTER_MUXDEMUX(FITS, fits); REGISTER_MUXDEMUX(FLAC, flac); REGISTER_DEMUXER (FLIC, flic); REGISTER_MUXDEMUX(FLV, flv); diff --git a/libavformat/fitsenc.c b/libavformat/fitsenc.c new file mode 100644 index 0000000..0dcdcdf --- /dev/null +++ b/libavformat/fitsenc.c @@ -0,0 +1,183 @@ +/* + * FITS muxer + * Copyright (c) 2017 Paras Chadha + * + * This file is part of FFmpeg. + * + * 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 + * FITS muxer. + */ + +#include "internal.h" + +typedef struct FITSContext { + int first_image; +} FITSContext; + +static int fits_write_header(AVFormatContext *s) +{ + FITSContext *fitsctx = s->priv_data; + fitsctx->first_image = 1; + return 0; +} + +/** + * Write one header line comprising of keyword and value(int) + * @param s AVFormat Context + * @param keyword pointer to the char array in which keyword is stored + * @param value the value corresponding to the keyword + * @param lines_written to keep track of lines written so far + * @return 0 + */ +static int write_keyword_value(AVFormatContext *s, const char *keyword, int value, int *lines_written) +{ + int len, ret; + uint8_t header[80]; + + len = strlen(keyword); + memset(header, ' ', sizeof(header)); + memcpy(header, keyword, len); + + header[8] = '='; + header[9] = ' '; + + ret = snprintf(header + 10, 70, "%d", value); + header[ret + 10] = ' '; + + avio_write(s->pb, header, sizeof(header)); + *lines_written += 1; + return 0; +} + +static int write_image_header(AVFormatContext *s) +{ + AVStream *st = s->streams[0]; + AVCodecParameters *encctx = st->codecpar; + FITSContext *fitsctx = s->priv_data; + uint8_t buffer[80]; + int bitpix, naxis, naxis3 = 1, bzero = 0, rgb = 0, lines_written = 0, lines_left; + + switch (encctx->format) { + case AV_PIX_FMT_GRAY8: + bitpix = 8; + naxis = 2; + break; + case AV_PIX_FMT_GRAY16BE: + bitpix = 16; + naxis = 2; + bzero = 32768; + break; + case AV_PIX_FMT_GBRP: + case AV_PIX_FMT_GBRAP: + bitpix = 8; + naxis = 3; + rgb = 1; + if (encctx->format == AV_PIX_FMT_GBRP) { + naxis3 = 3; + } else { + naxis3 = 4; + } + break; + case AV_PIX_FMT_GBRP16BE: + case AV_PIX_FMT_GBRAP16BE: + bitpix = 16; + naxis = 3; + rgb = 1; + if (encctx->format == AV_PIX_FMT_GBRP16BE) { + naxis3 = 3; + } else { + naxis3 = 4; + } + bzero = 32768; + break; + } + + if (fitsctx->first_image) { + memcpy(buffer, "SIMPLE = ", 10); + memset(buffer + 10, ' ', 70); + buffer[29] = 'T'; + avio_write(s->pb, buffer, sizeof(buffer)); + } else { + memcpy(buffer, "XTENSION= 'IMAGE '", 20); + memset(buffer + 20, ' ', 60); + avio_write(s->pb, buffer, sizeof(buffer)); + } + lines_written++; + + write_keyword_value(s, "BITPIX", bitpix, &lines_written); // no of bits per pixel + write_keyword_value(s, "NAXIS", naxis, &lines_written); // no of dimensions of image + write_keyword_value(s, "NAXIS1", encctx->width, &lines_written); // first dimension i.e. width + write_keyword_value(s, "NAXIS2", encctx->height, &lines_written); // second dimension i.e. height + + if (rgb) + write_keyword_value(s, "NAXIS3", naxis3, &lines_written); // third dimension to store RGBA planes + + if (!fitsctx->first_image) { + write_keyword_value(s, "PCOUNT", 0, &lines_written); + write_keyword_value(s, "GCOUNT", 1, &lines_written); + } else { + fitsctx->first_image = 0; + } + + /* + * Since FITS does not support unsigned 16 bit integers, + * BZERO = 32768 is used to store unsigned 16 bit integers as + * signed integers so that it can be read properly. + */ + if (bitpix == 16) + write_keyword_value(s, "BZERO", bzero, &lines_written); + + if (rgb) { + memcpy(buffer, "CTYPE3 = 'RGB '", 20); + memset(buffer + 20, ' ', 60); + avio_write(s->pb, buffer, sizeof(buffer)); + lines_written++; + } + + memcpy(buffer, "END", 3); + memset(buffer + 3, ' ', 77); + avio_write(s->pb, buffer, sizeof(buffer)); + lines_written++; + + lines_left = ((lines_written + 35) / 36) * 36 - lines_written; + memset(buffer, ' ', 80); + while (lines_left > 0) { + avio_write(s->pb, buffer, sizeof(buffer)); + lines_left--; + } + return 0; +} + +static int fits_write_packet(AVFormatContext *s, AVPacket *pkt) +{ + write_image_header(s); + avio_write(s->pb, pkt->data, pkt->size); + return 0; +} + +AVOutputFormat ff_fits_muxer = { + .name = "fits", + .long_name = NULL_IF_CONFIG_SMALL("Flexible Image Transport System"), + .extensions = "fits", + .priv_data_size = sizeof(FITSContext), + .audio_codec = AV_CODEC_ID_NONE, + .video_codec = AV_CODEC_ID_FITS, + .write_header = fits_write_header, + .write_packet = fits_write_packet, +}; diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c index 1297b1a..87b5ec2 100644 --- a/libavformat/img2enc.c +++ b/libavformat/img2enc.c @@ -62,6 +62,8 @@ static int write_header(AVFormatContext *s) if (st->codecpar->codec_id == AV_CODEC_ID_GIF) { img->muxer = "gif"; + } else if (st->codecpar->codec_id == AV_CODEC_ID_FITS) { + img->muxer = "fits"; } else if (st->codecpar->codec_id == AV_CODEC_ID_RAWVIDEO) { const char *str = strrchr(img->path, '.'); img->split_planes = str