On 7/20/2017 4:46 PM, Paras Chadha wrote: > Signed-off-by: Paras Chadha <paraschadh...@gmail.com> > --- > > Made the changes suggested. > > doc/general.texi | 2 +- > libavcodec/Makefile | 1 + > libavcodec/allcodecs.c | 2 +- > libavcodec/fitsenc.c | 237 > +++++++++++++++++++++++++++++++++++++++++++++++++ > libavformat/img2enc.c | 1 + > 5 files changed, 241 insertions(+), 2 deletions(-) > create mode 100644 libavcodec/fitsenc.c > > diff --git a/doc/general.texi b/doc/general.texi > index 01402cb..1ea7984 100644 > --- a/doc/general.texi > +++ b/doc/general.texi > @@ -592,7 +592,7 @@ following image formats are supported: > @tab Digital Picture Exchange > @item EXR @tab @tab X > @tab OpenEXR > -@item FITS @tab @tab X > +@item FITS @tab X @tab X > @tab Flexible Image Transport System > @item JPEG @tab X @tab X > @tab Progressive JPEG is not supported. > diff --git a/libavcodec/Makefile b/libavcodec/Makefile > index 5348ed9..9b1429f 100644 > --- a/libavcodec/Makefile > +++ b/libavcodec/Makefile > @@ -292,6 +292,7 @@ OBJS-$(CONFIG_FFV1_ENCODER) += ffv1enc.o ffv1.o > OBJS-$(CONFIG_FFWAVESYNTH_DECODER) += ffwavesynth.o > OBJS-$(CONFIG_FIC_DECODER) += fic.o > OBJS-$(CONFIG_FITS_DECODER) += fitsdec.o > +OBJS-$(CONFIG_FITS_ENCODER) += fitsenc.o > OBJS-$(CONFIG_FLAC_DECODER) += flacdec.o flacdata.o flac.o > OBJS-$(CONFIG_FLAC_ENCODER) += flacenc.o flacdata.o flac.o > vorbis_data.o > OBJS-$(CONFIG_FLASHSV_DECODER) += flashsv.o > diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c > index 8678ac2..7fe66f4 100644 > --- a/libavcodec/allcodecs.c > +++ b/libavcodec/allcodecs.c > @@ -192,7 +192,7 @@ static void register_all(void) > REGISTER_ENCDEC (FFV1, ffv1); > REGISTER_ENCDEC (FFVHUFF, ffvhuff); > REGISTER_DECODER(FIC, fic); > - REGISTER_DECODER(FITS, fits); > + REGISTER_ENCDEC (FITS, fits); > REGISTER_ENCDEC (FLASHSV, flashsv); > REGISTER_ENCDEC (FLASHSV2, flashsv2); > REGISTER_DECODER(FLIC, flic); > diff --git a/libavcodec/fitsenc.c b/libavcodec/fitsenc.c > new file mode 100644 > index 0000000..cdb662b > --- /dev/null > +++ b/libavcodec/fitsenc.c > @@ -0,0 +1,237 @@ > +/* > + * FITS image encoder > + * 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 image encoder > + * > + * Specification: https://fits.gsfc.nasa.gov/fits_standard.html Version 3.0 > + * > + * RGBA images are encoded as planes in RGBA order. So, NAXIS3 is 3 or 4 for > them. > + * Also CTYPE3 = 'RGB ' is added to the header to distinguish them from 3d > images. > + */ > + > +#include "libavutil/intreadwrite.h" > +#include "avcodec.h" > +#include "bytestream.h" > +#include "internal.h" > + > +typedef struct FITSContext { > + int first_image; > +} FITSContext; > + > +static av_cold int fits_encode_init(AVCodecContext *avctx) > +{ > + FITSContext * fitsctx = avctx->priv_data; > + fitsctx->first_image = 1; > + return 0; > +} > + > +static int write_keyword_value(uint8_t **bytestream, const char *keyword, > int value) > +{ > + int len, ret; > + uint8_t *header = *bytestream; > + len = strlen(keyword); > + > + memset(header, ' ', 80); > + memcpy(header, keyword, len); > + header[8] = '='; > + header[9] = ' '; > + header += 10; > + ret = snprintf(header, 70, "%d", value); > + header[ret] = ' '; > + > + *bytestream += 80; > + return 0; > +} > + > +static int fits_encode_frame(AVCodecContext *avctx, AVPacket *pkt, > + const AVFrame *pict, int *got_packet) > +{ > + AVFrame * const p = (AVFrame *)pict; > + FITSContext *fitsctx = avctx->priv_data; > + uint8_t *bytestream, *bytestream_start, *ptr; > + uint64_t header_size = 2880, data_size = 0, padded_data_size = 0; > + int ret, bitpix, naxis, naxis3 = 1, bzero = 0, i, j, k, t, rgb = 0; > + > + switch (avctx->pix_fmt) { > + 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_RGB24: > + case AV_PIX_FMT_RGBA: > + bitpix = 8; > + naxis = 3; > + rgb = 1; > + if (avctx->pix_fmt == AV_PIX_FMT_RGB24) { > + naxis3 = 3; > + } else { > + naxis3 = 4; > + } > + break; > + case AV_PIX_FMT_RGB48BE: > + case AV_PIX_FMT_RGBA64BE: > + bitpix = 16; > + naxis = 3; > + bzero = 32768; > + rgb = 1; > + if (avctx->pix_fmt == AV_PIX_FMT_RGB48BE) { > + naxis3 = 3; > + } else { > + naxis3 = 4; > + } > + break; > + default: > + av_log(avctx, AV_LOG_ERROR, "unsupported pixel format\n"); > + return AVERROR(EINVAL); > + } > + > + data_size = (bitpix >> 3) * avctx->height * avctx->width * naxis3; > + padded_data_size = ((data_size + 2879) / 2880 ) * 2880; > + > + if ((ret = ff_alloc_packet2(avctx, pkt, header_size + padded_data_size, > 0)) < 0) > + return ret; > + > + bytestream_start = > + bytestream = pkt->data; > + > + if (fitsctx->first_image) { > + memcpy(bytestream, "SIMPLE = ", 10); > + memset(bytestream + 10, ' ', 70); > + bytestream[29] = 'T'; > + } else { > + memcpy(bytestream, "XTENSION= 'IMAGE '", 20); > + memset(bytestream + 20, ' ', 60); > + } > + bytestream += 80; > + > + write_keyword_value(&bytestream, "BITPIX", bitpix); // no of > bits per pixel > + write_keyword_value(&bytestream, "NAXIS", naxis); // no of > dimensions of image > + write_keyword_value(&bytestream, "NAXIS1", avctx->width); // first > dimension i.e. width > + write_keyword_value(&bytestream, "NAXIS2", avctx->height); // second > dimension i.e. height > + > + if (rgb) > + write_keyword_value(&bytestream, "NAXIS3", naxis3); // third > dimension to store RGBA planes > + > + if (!fitsctx->first_image) { > + write_keyword_value(&bytestream, "PCOUNT", 0); > + write_keyword_value(&bytestream, "GCOUNT", 1); > + } 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(&bytestream, "BZERO", bzero); > + > + if (rgb) { > + memcpy(bytestream, "CTYPE3 = 'RGB '", 20); > + memset(bytestream + 20, ' ', 60); > + bytestream += 80; > + } > + > + memcpy(bytestream, "END", 3); > + memset(bytestream + 3, ' ', 77); > + bytestream += 80; > + > + t = header_size - (bytestream - bytestream_start); > + memset(bytestream, ' ', t); > + bytestream += t; > + > + if (rgb) { > + switch (avctx->pix_fmt) { > + case AV_PIX_FMT_RGB24: > + case AV_PIX_FMT_RGBA: > + for (k = 0; k < naxis3; k++) { > + for (i = 0; i < avctx->height; i++) { > + ptr = p->data[0] + (avctx->height - i - 1) * > p->linesize[0] + k; > + for (j = 0; j < avctx->width; j++) { > + bytestream_put_byte(&bytestream, ptr[0]); > + ptr += naxis3; > + } > + } > + } > + break; > + case AV_PIX_FMT_RGB48BE: > + case AV_PIX_FMT_RGBA64BE: > + for (k = 0; k < naxis3; k++) { > + for (i = 0; i < avctx->height; i++) { > + ptr = p->data[0] + (avctx->height - i - 1) * > p->linesize[0] + k * 2; > + for (j = 0; j < avctx->width; j++) { > + bytestream_put_be16(&bytestream, AV_RB16(ptr) - > bzero); > + ptr += naxis3 * 2; > + } > + } > + } > + break; > + } > + } else { > + for (i = 0; i < avctx->height; i++) { > + ptr = p->data[0] + (avctx->height - i - 1) * p->linesize[0]; > + if (bitpix == 16) { > + for (j = 0; j < avctx->width; j++) { > + bytestream_put_be16(&bytestream, AV_RB16(ptr) - bzero); > + ptr += 2; > + } > + } else { > + memcpy(bytestream, ptr, avctx->width); > + bytestream += avctx->width; > + } > + } > + } > + > + t = padded_data_size - data_size; > + memset(bytestream, 0, t); > + bytestream += t; > + > + pkt->size = bytestream - bytestream_start; > + pkt->flags |= AV_PKT_FLAG_KEY; > + *got_packet = 1; > + > + return 0; > +} > + > +AVCodec ff_fits_encoder = { > + .name = "fits", > + .long_name = NULL_IF_CONFIG_SMALL("Flexible Image Transport > System"), > + .type = AVMEDIA_TYPE_VIDEO, > + .id = AV_CODEC_ID_FITS, > + .priv_data_size = sizeof(FITSContext), > + .init = fits_encode_init, > + .encode2 = fits_encode_frame, > + .pix_fmts = (const enum AVPixelFormat[]) { AV_PIX_FMT_RGBA64BE, > + AV_PIX_FMT_RGB48BE, > + AV_PIX_FMT_RGBA, > + AV_PIX_FMT_RGB24, > + AV_PIX_FMT_GRAY16BE, > + AV_PIX_FMT_GRAY8, > + AV_PIX_FMT_NONE }, > +}; > diff --git a/libavformat/img2enc.c b/libavformat/img2enc.c > index 1297b1a..25283cc 100644 > --- a/libavformat/img2enc.c > +++ b/libavformat/img2enc.c > @@ -237,6 +237,7 @@ AVOutputFormat ff_image2_muxer = { > AVOutputFormat ff_image2pipe_muxer = { > .name = "image2pipe", > .long_name = NULL_IF_CONFIG_SMALL("piped image2 sequence"), > + .extensions = "fits",
This is probably wrong. Did you intend to add this extension to ff_image2_muxer instead? Also, libavformat changes should be in their own separate commits. > .priv_data_size = sizeof(VideoMuxData), > .video_codec = AV_CODEC_ID_MJPEG, > .write_header = write_header, > -- > 2.4.11 > > _______________________________________________ > ffmpeg-devel mailing list > ffmpeg-devel@ffmpeg.org > http://ffmpeg.org/mailman/listinfo/ffmpeg-devel > _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel