Re: [FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add DICOM decoder

2019-08-21 Thread Shivam


On 8/21/19 7:27 PM, Moritz Barsnick wrote:

On Tue, Aug 20, 2019 at 20:53:43 +0530, Shivam wrote:

Please review,

(Untested, just visual code inspection.)


+- DICOM decoder and demxer

Typo -> demuxer. Also, when splitting the commits, also split the
changes to the Changelog. (Can still be one line eventually.)


+.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS,

Possibly also AV_CODEC_PROP_INTRA_ONLY? (PNG doesn't have that either,
but other still image formats do.) Is DICOM a still image format, or
does it have multiple images and a sense of I-frames?


+static int extract_ed(AVCodecContext *avctx)

The return value is never used anywhere.


+int ed_s = avctx->extradata_size;

Feel free to name the variable with something containing "size", makes
the code somewhat easier to understand.


+static uint8_t apply_transfm(int64_t val, int64_t bitmask, int pix_pad,

  ^ I see no reason to save two letters in this 
name. ;-)


+static int decode_mono( AVCodecContext *avctx,
+const uint8_t *buf,
+AVFrame *p)

   ^ spurious space


+switch (bitsalloc) {
+case 8:

ffmpeg uses the same indentation level for "case" as for "switch".


+for (i = 0; i < size; i++) {
+if (pixrep)
+pix = (int8_t)bytestream_get_byte();
+else
+pix = (uint8_t)bytestream_get_byte();
+out[i] = pix;
+}

What is this doing? Is the cast to uint8_t an implicit "abs()"?
Could it just be:
pix = pixrep ? bytestream_get_byte() : 
FFABS(bytestream_get_byte());
out[i] = ...

Or in a somewhat different style:
uintXY_t val = bytestream_get_byte();
pix = pixrep ? byte : FFABS(byte);
 out[i] = ...


+default:
+av_log(avctx, AV_LOG_ERROR, "Bits allocated %d not supported\n", 
bitsalloc);
+return AVERROR_INVALIDDATA;

avctx->bits_per_coded_sample is a constant per file, right?
This "default" could be avoided if avctx->bits_per_coded_sample were
checked in init(), not in decode_frame().


+av_log(avctx, AV_LOG_ERROR, "Required buffer size is %d but recieved only 
%d\n", req_buf_size, buf_size);

typo: received


+void* bytes;

void *bytes


+char* desc; // description (from dicom dictionary)

char *desc;


+const uint8_t *d = p->buf;
+
+if (d[DICOM_PREAMBLE_SIZE] == 'D' &&
+d[DICOM_PREAMBLE_SIZE + 1] == 'I' &&
+d[DICOM_PREAMBLE_SIZE + 2] == 'C' &&
+d[DICOM_PREAMBLE_SIZE + 3] == 'M') {
+return AVPROBE_SCORE_MAX;

Would:
   if (!strncmp(p->buf, "DICM", 4)
also work? Seems much simpler to me. (Also skipping the intermediate
"d" variable.)


+if (de->bytes)
+av_free(de->bytes);
+if (de->desc)
+av_free(de->desc);

As Michael said, av_free() includes the NULL checks already.
Additionally, I believe the use of av_freep() is preferred for these
pointers. (Provokes a segfault on use after free, instead of "silently"
writing into / reading from that memory.)


+// detects transfer syntax
+static TransferSyntax get_transfer_sytax (const char *ts) {

   ^ typo: syntax

Could you also please not name the variable "ts", as that already has
too many other meanings. ;-) (Use e.g. "syntax".)


+static void set_dec_extradata(AVFormatContext *s, AVStream *st) {
+DICOMContext *dicom = s->priv_data;
+uint8_t *edp;
+int size = 20 + AV_INPUT_BUFFER_PADDING_SIZE;
+
+st->codecpar->extradata = (uint8_t *)av_malloc(size);
+edp = st->codecpar->extradata;
+bytestream_put_le32(>codecpar->extradata, dicom->interpret);
+bytestream_put_le32(>codecpar->extradata, dicom->pixrep);
+bytestream_put_le32(>codecpar->extradata, dicom->pixpad);
+bytestream_put_le32(>codecpar->extradata, dicom->slope);
+bytestream_put_le32(>codecpar->extradata, dicom->intcpt);
+st->codecpar->extradata = edp;
+st->codecpar->extradata_size = size;
+}

I'm not sure you're doing anything with edp here. Did you mean to use:
 bytestream_put_le32(, dicom->interpret);
?


+sprintf(key, "(%04x,%04x) %s", de->GroupNumber, de->ElementNumber, 
de->desc);

As Michael said, this can overflow "key". *Always* use snprintf.


+switch(de->VR) {
+case AT:

Indentation.


+static int set_multiframe_data(AVFormatContext *s, AVStream* st, DataElement 
*de)
+{
+DICOMContext *dicom = s->priv_data;
+
+if (de->GroupNumber != MF_GR_NB)
+return 0;
+
+switch (de->ElementNumber) {
+case 0x1063: // frame time
+dicom->delay = conv_DS(de);
+dicom->duration = dicom->delay * dicom->nb_frames;
+break;
+}
+return 0;
+}

Always returns 0.

Is this a switch/case, so that it can be expanded in the future?


+av_log(s, AV_LOG_WARNING,"Data 

Re: [FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add DICOM decoder

2019-08-21 Thread Moritz Barsnick
On Thu, Aug 22, 2019 at 00:28:28 +0530, Shivam wrote:
> >> + dicom->height = *(uint16_t *)bytes;
> > does this work on big endian ?
> > maybe you where looking for AV_RL16()
>
> Big endian DICOM files are retired and no longer supported by the standard.

What Michael means: What happens if you use this to decode a (little
endian) DICOM file on big endian hardware?

In other words: "dicom->height = *(uint16_t *)bytes" will map the bytes
into the big endian int in the wrong order, resulting in an incorrect
integer value. AV_RL16() (e.g.) handles this properly for you.

@Michael, do you have some short instructions on how to set up a big
endian system like your MIPS+qemu? Thanks.

Moritz
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add DICOM decoder

2019-08-21 Thread Shivam




 Forwarded Message 
Subject: 	Re: [FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add 
DICOM decoder

Date:   Thu, 22 Aug 2019 00:27:55 +0530
From:   Shivam 
To: Michael Niedermayer 




On 8/21/19 2:00 AM, Michael Niedermayer wrote:

On Tue, Aug 20, 2019 at 08:53:43PM +0530, Shivam wrote:

Sorry, for my previous mail, i forgot to attach the patch.

The patch contains support for Dicom files. The below features are 
supported

yet:-
Uncompressed DICOM files using any of the Implicit and Explicit VR 
formats.

Multiframe files are also supported.
To extract the metadata or info about the procedure, I have added an 
option

"-metadata." (The tags present in Dicom dictionary would be demuxed).

I have also uploaded DICOM samples here.
https://1drv.ms/u/s!AosJ9_SrP4Tsh2WoPfQAI8cSsqUs?e=ZMd5fR

Please review,

Thank you,
Shivam Goyal

Changelog | 1
libavcodec/Makefile | 1
libavcodec/allcodecs.c | 1
libavcodec/avcodec.h | 1
libavcodec/codec_desc.c | 7
libavcodec/dicom.c | 189 
libavcodec/version.h | 2
libavformat/Makefile | 1
libavformat/allformats.c | 1
libavformat/dicom.h | 108 +++
libavformat/dicomdec.c | 594 ++
libavformat/dicomdict.c | 716 
+++

libavformat/version.h | 2
13 files changed, 1622 insertions(+), 2 deletions(-)
d47b7ad6a9f16ce4e29a67a99800183f9056062d add_dicom.patch
From cd7ebe834278b29b0429b3f5b377154490ee159f Mon Sep 17 00:00:00 2001
From: Shivam Goyal <1998.goyal.shi...@gmail.com>
Date: Tue, 20 Aug 2019 20:03:02 +0530
Subject: [PATCH] lavc: add DICOM decoder, lavf: add DICOM demuxer

---
Changelog | 1 +
libavcodec/Makefile | 1 +
libavcodec/allcodecs.c | 1 +
libavcodec/avcodec.h | 1 +
libavcodec/codec_desc.c | 7 +
libavcodec/dicom.c | 189 +++
libavcodec/version.h | 2 +-
libavformat/Makefile | 1 +
libavformat/allformats.c | 1 +
libavformat/dicom.h | 108 ++
libavformat/dicomdec.c | 594 
libavformat/dicomdict.c | 716 +++
libavformat/version.h | 2 +-

libavformat and libavcodec changes should be in seperate patches



13 files changed, 1622 insertions(+), 2 deletions(-)
create mode 100644 libavcodec/dicom.c
create mode 100644 libavformat/dicom.h
create mode 100644 libavformat/dicomdec.c
create mode 100644 libavformat/dicomdict.c

diff --git a/Changelog b/Changelog
index c1f1237770..e04c3aa5f6 100644
--- a/Changelog
+++ b/Changelog
@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
version :
- Intel QSV-accelerated MJPEG decoding
- Intel QSV-accelerated VP9 decoding
+- DICOM decoder and demxer
version 4.2:
- tpad filter
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index e49188357b..799da8aef7 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -263,6 +263,7 @@ OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o 
dcadata.o dcahuff.o \

OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dca.o dcadata.o dcahuff.o \
dcaadpcm.o
OBJS-$(CONFIG_DDS_DECODER) += dds.o
+OBJS-$(CONFIG_DICOM_DECODER) += dicom.o
OBJS-$(CONFIG_DIRAC_DECODER) += diracdec.o dirac.o diracdsp.o 
diractab.o \

dirac_arith.o dirac_dwt.o dirac_vlc.o
OBJS-$(CONFIG_DFA_DECODER) += dfa.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 22985325e0..02a1afa7e8 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -83,6 +83,7 @@ extern AVCodec ff_cscd_decoder;
extern AVCodec ff_cyuv_decoder;
extern AVCodec ff_dds_decoder;
extern AVCodec ff_dfa_decoder;
+extern AVCodec ff_dicom_decoder;
extern AVCodec ff_dirac_decoder;
extern AVCodec ff_dnxhd_encoder;
extern AVCodec ff_dnxhd_decoder;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index d234271c5b..756e168c75 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -410,6 +410,7 @@ enum AVCodecID {
AV_CODEC_ID_SCREENPRESSO,
AV_CODEC_ID_RSCC,
AV_CODEC_ID_AVS2,
+ AV_CODEC_ID_DICOM,
AV_CODEC_ID_Y41P = 0x8000,
AV_CODEC_ID_AVRP,
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 4d033c20ff..ae9abdb2ba 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1403,6 +1403,13 @@ static const AVCodecDescriptor 
codec_descriptors[] = {

.long_name = NULL_IF_CONFIG_SMALL("AVS2-P2/IEEE1857.4"),
.props = AV_CODEC_PROP_LOSSY,
},
+ {
+ .id = AV_CODEC_ID_DICOM,
+ .type = AVMEDIA_TYPE_VIDEO,
+ .name = "dicom",
+ .long_name = NULL_IF_CONFIG_SMALL("DICOM (Digital Imaging and 
Communications in Medicine)"),

+ .props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS,
+ },
{
.id = AV_CODEC_ID_Y41P,
.type = AVMEDIA_TYPE_VIDEO,
diff --git a/libavcodec/dicom.c b/libavcodec/dicom.c
new file mode 100644
index 00..eaa378d944
--- /dev/null
+++ b/libavcodec/dicom.c
@@ -0,0 +1,189 @@
+/*
+ * DICOM decoder
+ * Copyright (c) 2019 Shivam Goyal
+ *
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the term

Re: [FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add DICOM decoder

2019-08-21 Thread Moritz Barsnick
On Tue, Aug 20, 2019 at 20:53:43 +0530, Shivam wrote:

One more. Some more nitpicking around this. Please use valgrind with
all your samples and some demuxing and decoding command lines.

> +static int dicom_read_packet(AVFormatContext *s, AVPacket *pkt)
> +{
> +DICOMContext *dicom = s->priv_data;
> +int metadata = dicom->metadata, ret;
> +AVDictionary **st_md;
> +char *key, *value;
> +AVStream  *st;
> +DataElement *de;
> +
> +if (s->nb_streams < 1) {
> +st = avformat_new_stream(s, NULL);
> +if (!st)
> +return AVERROR(ENOMEM);
> +st->codecpar->codec_id   = AV_CODEC_ID_DICOM;
> +st->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
> +st->start_time = 0;
> +avpriv_set_pts_info(st, 64, 1, 1000);
> +if (dicom->window != -1)
> +st->codecpar->profile = dicom->window;
> +if (dicom->level != -1)
> +st->codecpar->level = dicom->level;
> +} else
> +st = s->streams[0];
> +
> +st_md = >metadata;
> +dicom->inheader = 0;
> +if (dicom->frame_nb > 1 && dicom->frame_nb <= dicom->nb_frames)
> +goto inside_pix_data;
> +
> +for (;;) {
> +ret = avio_feof(s->pb);
> +if (ret)
> +return AVERROR_EOF;
> +
> +de = alloc_de();

Allocation failure needs to be checked:
if (!de)
return AVERROR(ENOMEM);

> +ret = read_de_metainfo(s,de);
> +if (ret < 0)
> +goto exit;
> +
> +if (de->GroupNumber == PIXEL_GR_NB && de->ElementNumber == 
> PIXELDATA_EL_NB) {
> +dicom->frame_size = de->VL / dicom->nb_frames;
> +set_dec_extradata(s, st);
> +inside_pix_data:
> +if (av_new_packet(pkt, dicom->frame_size) < 0)
> +return AVERROR(ENOMEM);

This leaks de. Instead:
if (av_new_packet(pkt, dicom->frame_size) < 0) {
ret = AVERROR(ENOMEM);
goto exit;
}

> +pkt->pos = avio_tell(s->pb);
> +pkt->stream_index = 0;
> +pkt->size = dicom->frame_size;
> +pkt->duration = dicom->delay;
> +ret = avio_read(s->pb, pkt->data, dicom->frame_size);
> +if (ret < 0) {
> +av_packet_unref(pkt);
> +goto exit;
> +}
> +dicom->frame_nb ++;
> +return ret;

This leaks everything (i.e. de and pkt). Instead:
dicom->frame_nb ++;
av_packet_unref(pkt);
goto exit;


> +} else if (de->GroupNumber == IMAGE_GR_NB || de->GroupNumber == 
> MF_GR_NB) {
> +ret = read_de_valuefield(s, de);
> +if (ret < 0)
> +goto exit;
> +set_imagegroup_data(s, st, de);
> +set_multiframe_data(s, st, de);
> +} else {
> +if (metadata || de->VL == UNDEFINED_VL)
> +ret = read_de_valuefield(s, de);
> +else
> +ret = avio_skip(s->pb, de->VL); // skip other elements
> +if (ret < 0)
> +goto exit;
> +}
> +if (metadata) {
> +ret = dicom_dict_find_elem_info(de);
> +if (ret < 0)
> +goto end_de;
> +key = get_key_str(de);
> +value = get_val_str(de);
> +av_dict_set(st_md, key, value, AV_DICT_DONT_STRDUP_KEY | 
> AV_DICT_DONT_STRDUP_VAL);
> +}
> +end_de:
> +free_de(de);
> +}
> +exit:
> +free_de(de);
> +if (ret < 0)
> +return ret;
> +return AVERROR_EOF;
> +}

And, as mentioned, "goto exit" can probably be a simple "break", but
that's up to you to verify that it still does the right thing.

Cheers,
Moritz
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Re: [FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add DICOM decoder

2019-08-21 Thread Moritz Barsnick
On Tue, Aug 20, 2019 at 20:53:43 +0530, Shivam wrote:
> I have also uploaded DICOM samples here.
> https://1drv.ms/u/s!AosJ9_SrP4Tsh2WoPfQAI8cSsqUs?e=ZMd5fR

I found something else, with valgrind:

> +static int read_implicit_seq_item(AVFormatContext *s, DataElement *de)
> +{
> +int ret, f = -2, i = 0;
> +
> +de->bytes = av_malloc(MAX_UNDEF_LENGTH);

This return value needs to be checked!

> +for(; i < MAX_UNDEF_LENGTH; ++i) {
> +ret = avio_rl16(s->pb);
> +if (ret < 0)
> +return ret;
> +
> +if (ret == SEQ_GR_NB)
> +f = i;
> +if (ret == SEQ_ITEM_DEL_EL_NB && f == i - 1) {
> +avio_skip(s->pb, 4);
> +break;
> +}
> +bytestream_put_le16((uint8_t **)>bytes, ret);
> +}
> +de->VL = (i - 1) * 2;
> +return 0;
> +}
> +
> +static int read_seq(AVFormatContext *s, DataElement *de) {
> +int i = 0, ret;
> +DICOMContext *dicom = s->priv_data;
> +DataElement *seq_data = (DataElement *)av_malloc(sizeof(DataElement) * 
> MAX_SEQ_LENGTH);

This is an array, right? There's a special av_malloc*() function for
allocating an array. (And the typecast is not required, IIUC.)

Furthermore, it is never freed.

Fixing free_de() as suggested alone is not sufficient either, the array
elements remain unfreed - those allocated here as seq_data[i]:

> +de->bytes = seq_data;
> +dicom->inseq = 1;
> +for (;i < MAX_SEQ_LENGTH; ++i) {
> +seq_data[i].bytes = NULL;
> +seq_data[i].desc = NULL;
> +seq_data[i].is_found = 0;
> +read_de_metainfo(s, seq_data + i);
> +if (seq_data[i].GroupNumber == SEQ_GR_NB
> +&& seq_data[i].ElementNumber == SEQ_DEL_EL_NB){
> +ret = i;
> +goto exit;
> +}
> +if (seq_data[i].VL == UNDEFINED_VL)
> +ret = read_implicit_seq_item(s, seq_data + i);

^ Here.

> +else
> +ret = read_de(s, seq_data + i);
> +if (ret < 0)
> +goto exit;
> +}

valgrind extract:

==20223== 10,000 bytes in 1 blocks are definitely lost in loss record 16 of 16
==20223==at 0x483AE4C: memalign (vg_replace_malloc.c:908)
==20223==by 0x483AF59: posix_memalign (vg_replace_malloc.c:1072)
==20223==by 0x5146F9: av_malloc (mem.c:87)
==20223==by 0x454C80: read_implicit_seq_item (dicomdec.c:371)
==20223==by 0x454C80: read_seq (dicomdec.c:410)
==20223==by 0x454C80: read_de_valuefield (dicomdec.c:424)
==20223==by 0x455312: dicom_read_packet (dicomdec.c:549)
==20223==by 0x4649C3: ff_read_packet (utils.c:856)
==20223==by 0x46594B: read_frame_internal (utils.c:1582)
==20223==by 0x46A001: avformat_find_stream_info (utils.c:3781)
==20223==by 0x4170BE: open_input_file (ffmpeg_opt.c:1126)
==20223==by 0x418A95: open_files (ffmpeg_opt.c:3275)
==20223==by 0x418A95: ffmpeg_parse_options (ffmpeg_opt.c:3315)
==20223==by 0x411875: main (ffmpeg.c:4872)




Furthermore, all your samples 000*.dcm give me the following error:

[dicom @ 0xfc26c0] Could not find codec parameters for stream 0 (Video: dicom, 
none): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options

Example:

[barsnick@paradise ffmpeg]$ ./ffmpeg_g -i 28.dcm -f null -
ffmpeg version N-94609-g406b3e902f Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 8 (GCC)
  configuration: --disable-doc --disable-everything --disable-network 
--disable-vdpau --enable-indev=lavfi --enable-demuxer=dicom 
--enable-muxer='null,hash,framehash,md5,framemd5' 
--enable-encoder='wrapped_avframe,rawvideo,pcm_s16le' 
--enable-decoder='rawvideo,pcm_f64le,dicom' 
--enable-filter='color,testsrc,anoisesrc,null,aresample' 
--enable-protocol='pipe,file'
  libavutil  56. 33.100 / 56. 33.100
  libavcodec 58. 56.100 / 58. 56.100
  libavformat58. 32.101 / 58. 32.101
  libavdevice58.  9.100 / 58.  9.100
  libavfilter 7. 58.100 /  7. 58.100
  libswscale  5.  6.100 /  5.  6.100
  libswresample   3.  6.100 /  3.  6.100
[dicom @ 0xfc76c0] Could not find codec parameters for stream 0 (Video: dicom, 
none): unspecified size
Consider increasing the value for the 'analyzeduration' and 'probesize' options
Input #0, dicom, from '28.dcm':
  Metadata:
(0002,0001) File Meta Information Version: [Binary data]
(0002,0002) Media Storage SOP Class UID: 1.2.840.10008.5.1.4.1.1.2
(0002,0003) Media Storage SOP Inst UID: 
1.3.6.1.4.1.14519.5.2.1.7014.4598.325035o92754234010375598120031
(0002,0010) Transfer Syntax UID: 1.2.840.10008.1.2.1
(0002,0012) Implementation Class UID: 1.2.40.0.13.1.1.1
(0002,0013) Implementation Version Name: dcm4che-1.4.35
  Duration: N/A, start: 0.00, bitrate: N/A
Stream #0:0: Video: dicom, none, 1k tbr, 1k tbn
Output #0, null, to 'pipe:':
Output file #0 does not contain any stream


Having compiled the demuxer and decoder, I do now understand that DICOM
images can have multiple "frames". 

Re: [FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add DICOM decoder

2019-08-21 Thread Moritz Barsnick
On Tue, Aug 20, 2019 at 20:53:43 +0530, Shivam wrote:
> Please review,

(Untested, just visual code inspection.)

> +- DICOM decoder and demxer

Typo -> demuxer. Also, when splitting the commits, also split the
changes to the Changelog. (Can still be one line eventually.)

> +.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS,

Possibly also AV_CODEC_PROP_INTRA_ONLY? (PNG doesn't have that either,
but other still image formats do.) Is DICOM a still image format, or
does it have multiple images and a sense of I-frames?

> +static int extract_ed(AVCodecContext *avctx)

The return value is never used anywhere.

> +int ed_s = avctx->extradata_size;

Feel free to name the variable with something containing "size", makes
the code somewhat easier to understand.

> +static uint8_t apply_transfm(int64_t val, int64_t bitmask, int pix_pad,
 ^ I see no reason to save two letters in this 
name. ;-)

> +static int decode_mono( AVCodecContext *avctx,
> +const uint8_t *buf,
> +AVFrame *p)
  ^ spurious space

> +switch (bitsalloc) {

> +case 8:

ffmpeg uses the same indentation level for "case" as for "switch".

> +for (i = 0; i < size; i++) {
> +if (pixrep)
> +pix = (int8_t)bytestream_get_byte();
> +else
> +pix = (uint8_t)bytestream_get_byte();
> +out[i] = pix;
> +}

What is this doing? Is the cast to uint8_t an implicit "abs()"?
Could it just be:
   pix = pixrep ? bytestream_get_byte() : 
FFABS(bytestream_get_byte());
   out[i] = ...

Or in a somewhat different style:
   uintXY_t val = bytestream_get_byte();
   pix = pixrep ? byte : FFABS(byte);
out[i] = ...

> +default:
> +av_log(avctx, AV_LOG_ERROR, "Bits allocated %d not supported\n", 
> bitsalloc);
> +return AVERROR_INVALIDDATA;

avctx->bits_per_coded_sample is a constant per file, right?
This "default" could be avoided if avctx->bits_per_coded_sample were
checked in init(), not in decode_frame().

> +av_log(avctx, AV_LOG_ERROR, "Required buffer size is %d but recieved 
> only %d\n", req_buf_size, buf_size);
typo: received

> +void* bytes;

void *bytes

> +char* desc; // description (from dicom dictionary)

char *desc;

> +const uint8_t *d = p->buf;
> +
> +if (d[DICOM_PREAMBLE_SIZE] == 'D' &&
> +d[DICOM_PREAMBLE_SIZE + 1] == 'I' &&
> +d[DICOM_PREAMBLE_SIZE + 2] == 'C' &&
> +d[DICOM_PREAMBLE_SIZE + 3] == 'M') {
> +return AVPROBE_SCORE_MAX;

Would:
  if (!strncmp(p->buf, "DICM", 4)
also work? Seems much simpler to me. (Also skipping the intermediate
"d" variable.)

> +if (de->bytes)
> +av_free(de->bytes);
> +if (de->desc)
> +av_free(de->desc);

As Michael said, av_free() includes the NULL checks already.
Additionally, I believe the use of av_freep() is preferred for these
pointers. (Provokes a segfault on use after free, instead of "silently"
writing into / reading from that memory.)

> +// detects transfer syntax
> +static TransferSyntax get_transfer_sytax (const char *ts) {
  ^ typo: syntax

Could you also please not name the variable "ts", as that already has
too many other meanings. ;-) (Use e.g. "syntax".)

> +static void set_dec_extradata(AVFormatContext *s, AVStream *st) {
> +DICOMContext *dicom = s->priv_data;
> +uint8_t *edp;
> +int size = 20 + AV_INPUT_BUFFER_PADDING_SIZE;
> +
> +st->codecpar->extradata = (uint8_t *)av_malloc(size);
> +edp = st->codecpar->extradata;
> +bytestream_put_le32(>codecpar->extradata, dicom->interpret);
> +bytestream_put_le32(>codecpar->extradata, dicom->pixrep);
> +bytestream_put_le32(>codecpar->extradata, dicom->pixpad);
> +bytestream_put_le32(>codecpar->extradata, dicom->slope);
> +bytestream_put_le32(>codecpar->extradata, dicom->intcpt);
> +st->codecpar->extradata = edp;
> +st->codecpar->extradata_size = size;
> +}

I'm not sure you're doing anything with edp here. Did you mean to use:
bytestream_put_le32(, dicom->interpret);
?

> +sprintf(key, "(%04x,%04x) %s", de->GroupNumber, de->ElementNumber, 
> de->desc);

As Michael said, this can overflow "key". *Always* use snprintf.

> +switch(de->VR) {
> +case AT:

Indentation.

> +static int set_multiframe_data(AVFormatContext *s, AVStream* st, DataElement 
> *de)
> +{
> +DICOMContext *dicom = s->priv_data;
> +
> +if (de->GroupNumber != MF_GR_NB)
> +return 0;
> +
> +switch (de->ElementNumber) {
> +case 0x1063: // frame time
> +dicom->delay = conv_DS(de);
> +dicom->duration = dicom->delay * dicom->nb_frames;
> +break;
> +}
> +return 0;
> +}

Always returns 0.

Is this a switch/case, so that it can be 

Re: [FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add DICOM decoder

2019-08-20 Thread Michael Niedermayer
On Tue, Aug 20, 2019 at 08:53:43PM +0530, Shivam wrote:
> Sorry, for my previous mail, i forgot to attach the patch.
> 
> The patch contains support for Dicom files. The below features are supported
> yet:-
> Uncompressed DICOM files using any of the Implicit and Explicit VR formats.
> Multiframe files are also supported.
> To extract the metadata or info about the procedure, I have added an option
> "-metadata." (The tags present in Dicom dictionary would be demuxed).
> 
> I have also uploaded DICOM samples here.
> https://1drv.ms/u/s!AosJ9_SrP4Tsh2WoPfQAI8cSsqUs?e=ZMd5fR
> 
> Please review,
> 
> Thank you,
> Shivam Goyal
> 

>  Changelog|1 
>  libavcodec/Makefile  |1 
>  libavcodec/allcodecs.c   |1 
>  libavcodec/avcodec.h |1 
>  libavcodec/codec_desc.c  |7 
>  libavcodec/dicom.c   |  189 
>  libavcodec/version.h |2 
>  libavformat/Makefile |1 
>  libavformat/allformats.c |1 
>  libavformat/dicom.h  |  108 +++
>  libavformat/dicomdec.c   |  594 ++
>  libavformat/dicomdict.c  |  716 
> +++
>  libavformat/version.h|2 
>  13 files changed, 1622 insertions(+), 2 deletions(-)
> d47b7ad6a9f16ce4e29a67a99800183f9056062d  add_dicom.patch
> From cd7ebe834278b29b0429b3f5b377154490ee159f Mon Sep 17 00:00:00 2001
> From: Shivam Goyal <1998.goyal.shi...@gmail.com>
> Date: Tue, 20 Aug 2019 20:03:02 +0530
> Subject: [PATCH] lavc: add DICOM decoder, lavf: add DICOM demuxer
> 

> ---
>  Changelog|   1 +
>  libavcodec/Makefile  |   1 +
>  libavcodec/allcodecs.c   |   1 +
>  libavcodec/avcodec.h |   1 +
>  libavcodec/codec_desc.c  |   7 +
>  libavcodec/dicom.c   | 189 +++
>  libavcodec/version.h |   2 +-
>  libavformat/Makefile |   1 +
>  libavformat/allformats.c |   1 +
>  libavformat/dicom.h  | 108 ++
>  libavformat/dicomdec.c   | 594 
>  libavformat/dicomdict.c  | 716 +++
>  libavformat/version.h|   2 +-

libavformat and libavcodec changes should be in seperate patches


>  13 files changed, 1622 insertions(+), 2 deletions(-)
>  create mode 100644 libavcodec/dicom.c
>  create mode 100644 libavformat/dicom.h
>  create mode 100644 libavformat/dicomdec.c
>  create mode 100644 libavformat/dicomdict.c
> 
> diff --git a/Changelog b/Changelog
> index c1f1237770..e04c3aa5f6 100644
> --- a/Changelog
> +++ b/Changelog
> @@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
>  version :
>  - Intel QSV-accelerated MJPEG decoding
>  - Intel QSV-accelerated VP9 decoding
> +- DICOM decoder and demxer
>  
>  version 4.2:
>  - tpad filter
> diff --git a/libavcodec/Makefile b/libavcodec/Makefile
> index e49188357b..799da8aef7 100644
> --- a/libavcodec/Makefile
> +++ b/libavcodec/Makefile
> @@ -263,6 +263,7 @@ OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o 
> dcadata.o dcahuff.o \
>  OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dca.o dcadata.o dcahuff.o 
> \
>dcaadpcm.o
>  OBJS-$(CONFIG_DDS_DECODER) += dds.o
> +OBJS-$(CONFIG_DICOM_DECODER)   += dicom.o
>  OBJS-$(CONFIG_DIRAC_DECODER)   += diracdec.o dirac.o diracdsp.o 
> diractab.o \
>dirac_arith.o dirac_dwt.o 
> dirac_vlc.o
>  OBJS-$(CONFIG_DFA_DECODER) += dfa.o
> diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
> index 22985325e0..02a1afa7e8 100644
> --- a/libavcodec/allcodecs.c
> +++ b/libavcodec/allcodecs.c
> @@ -83,6 +83,7 @@ extern AVCodec ff_cscd_decoder;
>  extern AVCodec ff_cyuv_decoder;
>  extern AVCodec ff_dds_decoder;
>  extern AVCodec ff_dfa_decoder;
> +extern AVCodec ff_dicom_decoder;
>  extern AVCodec ff_dirac_decoder;
>  extern AVCodec ff_dnxhd_encoder;
>  extern AVCodec ff_dnxhd_decoder;
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index d234271c5b..756e168c75 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -410,6 +410,7 @@ enum AVCodecID {
>  AV_CODEC_ID_SCREENPRESSO,
>  AV_CODEC_ID_RSCC,
>  AV_CODEC_ID_AVS2,
> +AV_CODEC_ID_DICOM,
>  
>  AV_CODEC_ID_Y41P = 0x8000,
>  AV_CODEC_ID_AVRP,
> diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
> index 4d033c20ff..ae9abdb2ba 100644
> --- a/libavcodec/codec_desc.c
> +++ b/libavcodec/codec_desc.c
> @@ -1403,6 +1403,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
>  .long_name = NULL_IF_CONFIG_SMALL("AVS2-P2/IEEE1857.4"),
>  .props = AV_CODEC_PROP_LOSSY,
>  },
> +{
> +.id= AV_CODEC_ID_DICOM,
> +.type  = AVMEDIA_TYPE_VIDEO,
> +.name  = "dicom",
> +.long_name = NULL_IF_CONFIG_SMALL("DICOM (Digital Imaging and 
> Communications in Medicine)"),
> +.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS,
> +

[FFmpeg-devel] [PATCH] lavf: Add DICOM demuxer, lavc: Add DICOM decoder

2019-08-20 Thread Shivam

Sorry, for my previous mail, i forgot to attach the patch.

The patch contains support for Dicom files. The below features are 
supported yet:-

Uncompressed DICOM files using any of the Implicit and Explicit VR formats.
Multiframe files are also supported.
To extract the metadata or info about the procedure, I have added an 
option "-metadata." (The tags present in Dicom dictionary would be demuxed).


I have also uploaded DICOM samples here.
https://1drv.ms/u/s!AosJ9_SrP4Tsh2WoPfQAI8cSsqUs?e=ZMd5fR

Please review,

Thank you,
Shivam Goyal

>From cd7ebe834278b29b0429b3f5b377154490ee159f Mon Sep 17 00:00:00 2001
From: Shivam Goyal <1998.goyal.shi...@gmail.com>
Date: Tue, 20 Aug 2019 20:03:02 +0530
Subject: [PATCH] lavc: add DICOM decoder, lavf: add DICOM demuxer

---
 Changelog|   1 +
 libavcodec/Makefile  |   1 +
 libavcodec/allcodecs.c   |   1 +
 libavcodec/avcodec.h |   1 +
 libavcodec/codec_desc.c  |   7 +
 libavcodec/dicom.c   | 189 +++
 libavcodec/version.h |   2 +-
 libavformat/Makefile |   1 +
 libavformat/allformats.c |   1 +
 libavformat/dicom.h  | 108 ++
 libavformat/dicomdec.c   | 594 
 libavformat/dicomdict.c  | 716 +++
 libavformat/version.h|   2 +-
 13 files changed, 1622 insertions(+), 2 deletions(-)
 create mode 100644 libavcodec/dicom.c
 create mode 100644 libavformat/dicom.h
 create mode 100644 libavformat/dicomdec.c
 create mode 100644 libavformat/dicomdict.c

diff --git a/Changelog b/Changelog
index c1f1237770..e04c3aa5f6 100644
--- a/Changelog
+++ b/Changelog
@@ -4,6 +4,7 @@ releases are sorted from youngest to oldest.
 version :
 - Intel QSV-accelerated MJPEG decoding
 - Intel QSV-accelerated VP9 decoding
+- DICOM decoder and demxer
 
 version 4.2:
 - tpad filter
diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index e49188357b..799da8aef7 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -263,6 +263,7 @@ OBJS-$(CONFIG_DCA_DECODER) += dcadec.o dca.o dcadata.o dcahuff.o \
 OBJS-$(CONFIG_DCA_ENCODER) += dcaenc.o dca.o dcadata.o dcahuff.o \
   dcaadpcm.o
 OBJS-$(CONFIG_DDS_DECODER) += dds.o
+OBJS-$(CONFIG_DICOM_DECODER)   += dicom.o
 OBJS-$(CONFIG_DIRAC_DECODER)   += diracdec.o dirac.o diracdsp.o diractab.o \
   dirac_arith.o dirac_dwt.o dirac_vlc.o
 OBJS-$(CONFIG_DFA_DECODER) += dfa.o
diff --git a/libavcodec/allcodecs.c b/libavcodec/allcodecs.c
index 22985325e0..02a1afa7e8 100644
--- a/libavcodec/allcodecs.c
+++ b/libavcodec/allcodecs.c
@@ -83,6 +83,7 @@ extern AVCodec ff_cscd_decoder;
 extern AVCodec ff_cyuv_decoder;
 extern AVCodec ff_dds_decoder;
 extern AVCodec ff_dfa_decoder;
+extern AVCodec ff_dicom_decoder;
 extern AVCodec ff_dirac_decoder;
 extern AVCodec ff_dnxhd_encoder;
 extern AVCodec ff_dnxhd_decoder;
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index d234271c5b..756e168c75 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -410,6 +410,7 @@ enum AVCodecID {
 AV_CODEC_ID_SCREENPRESSO,
 AV_CODEC_ID_RSCC,
 AV_CODEC_ID_AVS2,
+AV_CODEC_ID_DICOM,
 
 AV_CODEC_ID_Y41P = 0x8000,
 AV_CODEC_ID_AVRP,
diff --git a/libavcodec/codec_desc.c b/libavcodec/codec_desc.c
index 4d033c20ff..ae9abdb2ba 100644
--- a/libavcodec/codec_desc.c
+++ b/libavcodec/codec_desc.c
@@ -1403,6 +1403,13 @@ static const AVCodecDescriptor codec_descriptors[] = {
 .long_name = NULL_IF_CONFIG_SMALL("AVS2-P2/IEEE1857.4"),
 .props = AV_CODEC_PROP_LOSSY,
 },
+{
+.id= AV_CODEC_ID_DICOM,
+.type  = AVMEDIA_TYPE_VIDEO,
+.name  = "dicom",
+.long_name = NULL_IF_CONFIG_SMALL("DICOM (Digital Imaging and Communications in Medicine)"),
+.props = AV_CODEC_PROP_LOSSY | AV_CODEC_PROP_LOSSLESS,
+},
 {
 .id= AV_CODEC_ID_Y41P,
 .type  = AVMEDIA_TYPE_VIDEO,
diff --git a/libavcodec/dicom.c b/libavcodec/dicom.c
new file mode 100644
index 00..eaa378d944
--- /dev/null
+++ b/libavcodec/dicom.c
@@ -0,0 +1,189 @@
+/*
+ * DICOM decoder
+ * Copyright (c) 2019 Shivam Goyal
+ *
+ * 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