From patchwork Sat Aug 19 20:43:23 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paras X-Patchwork-Id: 4752 Delivered-To: ffmpegpatchwork@gmail.com Received: by 10.103.46.211 with SMTP id u202csp2277578vsu; Sat, 19 Aug 2017 13:43:42 -0700 (PDT) X-Received: by 10.28.210.139 with SMTP id j133mr3916522wmg.104.1503175422839; Sat, 19 Aug 2017 13:43:42 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1503175422; cv=none; d=google.com; s=arc-20160816; b=k+V3v8QETlLMXsp+sirkGy+KQTt6RQe7Sozd3muOCRFsQVLZebCGRrelGAuOHPK0Ro 2D8jVXZLzl+a4VSxjb8jBMonFigIolnQ4gbMUpkW22HKsTJ77hbL8cAFgBnemhEQ15cP 1zyykIVNB6wzsTfA7NFMlEpOYO/VSYweA+PflYN3XsHorbjFSm8YvDdzwHTtfgEHFwim NDpesUCzhBS7B5QvN+480r2kyt8Rv34cTi04j6JR8Vm8KKvTJLNLbo99YbwV1lAK2vWY 0TE1hzjyMgF06R/p56xTnFty3L6j7qKHhTkg8/NXsRenAPwgctRXKZUAYA3YTX9UvTiJ Kj9A== 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=f2gR1U09CPMbwx6BXclo5m9yYJ2YmUieYKswv3SjZYk=; b=g+zGhZTnSnp6jA9s3BRDt047BuQN+Czu8c0ScHh4qFl4WPQg36LRPXPIDlvrUJTIaX yPwGpNeu9dGfsFx11lmcCCDv298RRd/h41a5aAZgmQ7UsQ9ms84x0z7gcJbL+Bc4l36H IwiKGPQBrgLYhVu+OnMLr1FGvMEiTYGH0aQ4NtrFk48Gch29UXJTW4uaGmSbTFWKElKa lZdLha+6AybOn+FC4E5ovc4mX7L4znm6U7a16msqxIP4bBzkyOwv529JVq8oCNs/wCYa TQitf78wbENG4XaYUEkvv9N+8pQZHS8xjTPUDg82d4EB4PebCxymcMVDaQlqP47lUXqM 7CCQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@gmail.com header.s=20161025 header.b=plXVV8aN; 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 t5si2991477wmg.3.2017.08.19.13.43.41; Sat, 19 Aug 2017 13:43:42 -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=plXVV8aN; 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 887C86882CA; Sat, 19 Aug 2017 23:43:33 +0300 (EEST) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-pf0-f193.google.com (mail-pf0-f193.google.com [209.85.192.193]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 6252668040B for ; Sat, 19 Aug 2017 23:43:27 +0300 (EEST) Received: by mail-pf0-f193.google.com with SMTP id t83so3438404pfj.3 for ; Sat, 19 Aug 2017 13:43:33 -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=+g0LlhLJcNVoveSw1+0reJuQXCS2Gt4NxnGWoqVz5oI=; b=plXVV8aNeGUVlEIZntUy7bp17n1juW8QqOn1CdcSlDobDoOng/e/JcCgszq9sYrVJ2 jpgdLhPQMpWPW5S5IwrvBHJkrwjo+ttSbEkFG7BkRj9US7NadDp212bAOsoeJ6qhak8n Il826h+oBxCGz0kpLoo5rZ254XM33lDqMN2yIj3QLqLJD4dd/ZA2aV40zIWWcnRabk/b PmrLMHJ9rLPOxsbwRjcFPgRY4kNuCupNAmKNo9Nf6uVm/2D+PhxrS4s7gi3tln7TsBVS RIfQ6oPQFCq4MWCSzduJ93pXSgoUiFeizPqv51SZcLF06iDuGJ5Rd6mfnFsf1H4WVv2L 16LQ== 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=+g0LlhLJcNVoveSw1+0reJuQXCS2Gt4NxnGWoqVz5oI=; b=d4DrONaI1XBIBaD3cJS9JdGWDROsVQaY+jdzA5C1WID5iFBwWJ5+PdCbwAGknqxsk8 2wmr78lOS7TuVndCPJ+N6l1BveWNbnp8h/sJgd3vQFqG5wAUm5xCnO4/CxKBoa+QlpOw vOt3vVaLojCe05Flv8eFNvcjGmHLXiJ+hQVsa00LjXymKKNe5n+4eZjc0FTheV1DJtnJ 3bvFj6FSMNewcf+g6xXK+1p0eGo32K4lXVlclsgAowiVvnWx2FRwB0qlU6Nqde0DzKeP wwr59bCqRDLgyVsP59K9Ut+FgDLLPIJaJdohOe+CT67gWurLwBh5XxNVjdgagFrWRB8Q edvg== X-Gm-Message-State: AHYfb5hs0XlowT9YF6hYjm1MsYn9rE2CplsRHNIO6mvHEoM8MfH/7QHJ ixVqcVFiGiFzY2Qb X-Received: by 10.99.103.68 with SMTP id b65mr12167418pgc.453.1503175411951; Sat, 19 Aug 2017 13:43:31 -0700 (PDT) Received: from dhcppc9.localdomain ([124.253.9.90]) by smtp.gmail.com with ESMTPSA id 204sm15879361pga.85.2017.08.19.13.43.29 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sat, 19 Aug 2017 13:43:31 -0700 (PDT) From: Paras Chadha To: ffmpeg-devel@ffmpeg.org Date: Sun, 20 Aug 2017 02:13:23 +0530 Message-Id: <1503175403-27090-1-git-send-email-paraschadha18@gmail.com> X-Mailer: git-send-email 2.4.11 In-Reply-To: <1502088236-22172-1-git-send-email-paraschadha18@gmail.com> References: <1502088236-22172-1-git-send-email-paraschadha18@gmail.com> 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 --- Add FATE coverage libavformat/Makefile | 1 + libavformat/allformats.c | 2 +- libavformat/fitsenc.c | 183 +++++++++++++++++++++++++++++++++++++++++++++++ libavformat/img2enc.c | 2 + tests/fate/avformat.mak | 1 + tests/lavf-regression.sh | 9 +++ tests/ref/lavf/fits | 18 +++++ 7 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 libavformat/fitsenc.c create mode 100644 tests/ref/lavf/fits -- 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 diff --git a/tests/fate/avformat.mak b/tests/fate/avformat.mak index 82a531c..c4cf2bc 100644 --- a/tests/fate/avformat.mak +++ b/tests/fate/avformat.mak @@ -10,6 +10,7 @@ FATE_LAVF-$(call ENCDEC, PCM_S16BE, CAF) += caf FATE_LAVF-$(call ENCDEC, DPX, IMAGE2) += dpx FATE_LAVF-$(call ENCDEC2, DVVIDEO, PCM_S16LE, AVI) += dv_fmt FATE_LAVF-$(call ENCDEC2, MPEG1VIDEO, MP2, FFM) += ffm +FATE_LAVF-$(call ENCDEC, FITS, IMAGE2) += fits FATE_LAVF-$(call ENCDEC, RAWVIDEO, FILMSTRIP) += flm FATE_LAVF-$(call ENCDEC, FLV, FLV) += flv_fmt FATE_LAVF-$(call ENCDEC, GIF, IMAGE2) += gif diff --git a/tests/lavf-regression.sh b/tests/lavf-regression.sh index eda40f2..d9026de 100755 --- a/tests/lavf-regression.sh +++ b/tests/lavf-regression.sh @@ -230,6 +230,15 @@ do_avconv $file $DEC_OPTS -f image2 -vcodec pgmyuv -i $raw_src $ENC_OPTS -t 1 -q #do_avconv_crc $file -i $target_path/$file fi +if [ -n "$do_fits" ] ; then +pix_fmts="gray gray16be gbrp gbrap gbrp16be gbrap16be" +for pix_fmt in $pix_fmts ; do + file=${outfile}${pix_fmt}lavf.fits + do_avconv $file $DEC_OPTS -f image2 -vcodec pgmyuv -i $raw_src $ENC_OPTS -pix_fmt $pix_fmt + do_avconv_crc $file $DEC_OPTS -i $target_path/$file -pix_fmt $pix_fmt +done +fi + # image formats if [ -n "$do_pgm" ] ; then diff --git a/tests/ref/lavf/fits b/tests/ref/lavf/fits new file mode 100644 index 0000000..489542b --- /dev/null +++ b/tests/ref/lavf/fits @@ -0,0 +1,18 @@ +ed9fd697d0d782df6201f6a2db184552 *./tests/data/lavf/graylavf.fits +5328000 ./tests/data/lavf/graylavf.fits +./tests/data/lavf/graylavf.fits CRC=0xbacf446c +48e6caf6a59e32f9a8a39979c9183a7f *./tests/data/lavf/gray16belavf.fits +10368000 ./tests/data/lavf/gray16belavf.fits +./tests/data/lavf/gray16belavf.fits CRC=0xae2b58d4 +be2f7112fd193c9a909304c81e662769 *./tests/data/lavf/gbrplavf.fits +15408000 ./tests/data/lavf/gbrplavf.fits +./tests/data/lavf/gbrplavf.fits CRC=0x04ed3828 +c89a72185cfad363aa9cc42e84fed301 *./tests/data/lavf/gbraplavf.fits +20448000 ./tests/data/lavf/gbraplavf.fits +./tests/data/lavf/gbraplavf.fits CRC=0x032a6409 +d539b9e02f5ab8fb85717c8adb60b6cc *./tests/data/lavf/gbrp16belavf.fits +30672000 ./tests/data/lavf/gbrp16belavf.fits +./tests/data/lavf/gbrp16belavf.fits CRC=0x81897ff7 +3dc3622fb09a338b406d8a12a30f2545 *./tests/data/lavf/gbrap16belavf.fits +40752000 ./tests/data/lavf/gbrap16belavf.fits +./tests/data/lavf/gbrap16belavf.fits CRC=0x247dd7b9