[FFmpeg-devel] [RFC PATCH] libavformat/rtpdec_jpeg2000: RTP Demuxing for JPEG2000

Gautam Ramakrishnan gautamramk at gmail.com
Tue Jul 21 19:46:11 EEST 2020


On Tue, Jul 21, 2020 at 10:08 PM <gautamramk at gmail.com> wrote:
>
> From: Gautam Ramakrishnan <gautamramk at gmail.com>
>
> This patch adds support to receive JPEG2000 RTP streams.
> ---
>  libavformat/Makefile          |   1 +
>  libavformat/rtpdec.c          |   1 +
>  libavformat/rtpdec_formats.h  |   1 +
>  libavformat/rtpdec_jpeg2000.c | 116 ++++++++++++++++++++++++++++++++++
>  4 files changed, 119 insertions(+)
>  create mode 100644 libavformat/rtpdec_jpeg2000.c
>
> diff --git a/libavformat/Makefile b/libavformat/Makefile
> index 62d8cbb54e..4495047e3a 100644
> --- a/libavformat/Makefile
> +++ b/libavformat/Makefile
> @@ -46,6 +46,7 @@ OBJS-$(CONFIG_RTPDEC)                    += rdt.o                       \
>                                              rtpdec_hevc.o               \
>                                              rtpdec_ilbc.o               \
>                                              rtpdec_jpeg.o               \
> +                                            rtpdec_jpeg2000.o           \
>                                              rtpdec_latm.o               \
>                                              rtpdec_mpa_robust.o         \
>                                              rtpdec_mpeg12.o             \
> diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
> index 3d5b200099..b47dfdfebc 100644
> --- a/libavformat/rtpdec.c
> +++ b/libavformat/rtpdec.c
> @@ -118,6 +118,7 @@ static const RTPDynamicProtocolHandler *rtp_dynamic_protocol_handler_list[] = {
>      &ff_vorbis_dynamic_handler,
>      &ff_vp8_dynamic_handler,
>      &ff_vp9_dynamic_handler,
> +    &ff_jpeg2000_dynamic_handler,
>      &gsm_dynamic_handler,
>      &l24_dynamic_handler,
>      &opus_dynamic_handler,
> diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
> index dad2b8ac1b..78ea4fb384 100644
> --- a/libavformat/rtpdec_formats.h
> +++ b/libavformat/rtpdec_formats.h
> @@ -89,5 +89,6 @@ extern const RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler;
>  extern const RTPDynamicProtocolHandler ff_vorbis_dynamic_handler;
>  extern const RTPDynamicProtocolHandler ff_vp8_dynamic_handler;
>  extern const RTPDynamicProtocolHandler ff_vp9_dynamic_handler;
> +extern const RTPDynamicProtocolHandler ff_jpeg2000_dynamic_handler;
>
>  #endif /* AVFORMAT_RTPDEC_FORMATS_H */
> diff --git a/libavformat/rtpdec_jpeg2000.c b/libavformat/rtpdec_jpeg2000.c
> new file mode 100644
> index 0000000000..b5337a9cdb
> --- /dev/null
> +++ b/libavformat/rtpdec_jpeg2000.c
> @@ -0,0 +1,116 @@
> +/*
> + * Code for the RTP depacketization of JPEG2000.
> + * Copyright (c) 2020 Gautam Ramakrishnan
> + *
> + * 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
> + * @brief JPEG2000 / RTP Code
> + * @author Gautam Ramakrishnan
> + */
> +
> +#include "rtpdec_formats.h"
> +#include "avio_internal.h"
> +#include "internal.h"
> +#include "libavutil/attributes.h"
> +#include "libavutil/avstring.h"
> +#include "libavcodec/get_bits.h"
> +
> +#define PAYLOAD_HDR_SIZ 8
> +
> +/**
> + * RTP/JPEG specific private data.
> + */
> +struct PayloadContext {
> +    AVIOContext *frame;         // current frame buffer
> +    uint32_t    timestamp;      // current frame timestamp
> +};
> +
> +static void jpeg2000_close_context(PayloadContext *data)
> +{
> +    ffio_free_dyn_buf(&data->frame);
> +}
> +
> +static int jpeg2000_parse_packet(AVFormatContext *ctx, PayloadContext *data,
> +                                AVStream *st, AVPacket *pkt, uint32_t *timestamp,
> +                                const uint8_t *buf, int len, uint16_t seq,
> +                                int flags)
> +{
> +    int ret;
> +    int off;
> +
> +    if (len < 8) {
> +        av_log(ctx, AV_LOG_ERROR, "Too short RTP/JPEG packet.\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +    off = (uint64_t)AV_RB64(buf) & 0xFFFFFF;
> +    buf += 8;
> +    len -= 8;
> +    if (!off) {
> +        /* Skip the current frame in case of the end packet
> +         * has been lost somewhere. */
> +        ffio_free_dyn_buf(&data->frame);
> +
> +        if ((ret = avio_open_dyn_buf(&data->frame)) < 0)
> +            return ret;
> +        data->timestamp = *timestamp;
> +    }
> +    if (!data->frame) {
> +        av_log(ctx, AV_LOG_ERROR,
> +               "Received packet without a start chunk; dropping frame.\n");
> +        return AVERROR(EAGAIN);
> +    }
> +
> +    if (data->timestamp != *timestamp) {
> +        /* Skip the current frame if timestamp is incorrect.
> +         * A start packet has been lost somewhere. */
> +        ffio_free_dyn_buf(&data->frame);
> +        av_log(ctx, AV_LOG_ERROR, "RTP timestamps don't match.\n");
> +        return AVERROR_INVALIDDATA;
> +    }
> +
> +    if (off != avio_tell(data->frame)) {
> +        av_log(ctx, AV_LOG_ERROR,
> +               "Missing packets; dropping frame.\n");
> +        return AVERROR(EAGAIN);
> +    }
> +    /* Copy data to frame buffer. */
> +    avio_write(data->frame, buf, len);
> +
> +    if (flags & RTP_FLAG_MARKER) {
> +        /* Prepare the JPEG2000 packet. */
> +        if ((ret = ff_rtp_finalize_packet(pkt, &data->frame, st->index)) < 0) {
> +            av_log(ctx, AV_LOG_ERROR,
> +                   "Error occurred when getting frame buffer.\n");
> +            return ret;
> +        }
> +
> +        return 0;
> +    }
> +    return AVERROR(EAGAIN);
> +}
> +
> +const RTPDynamicProtocolHandler ff_jpeg2000_dynamic_handler = {
> +    .enc_name           = "jpeg2000",
> +    .codec_type         = AVMEDIA_TYPE_VIDEO,
> +    .codec_id           = AV_CODEC_ID_JPEG2000,
> +    .priv_data_size     = sizeof(PayloadContext),
> +    .parse_packet       = jpeg2000_parse_packet,
> +    .close              = jpeg2000_close_context,
> +};
> --
> 2.17.1
>

This was tested using a GStreamer RTSP server.
An mj2 file was encoded using gst_launch and hosted
using the GStreamer RTSP server.

Additionally I would really appreciate some advice on how
to test the encoder.
>From my understanding, in most cases RTSP servers perform
the encoding operations and stream to clients. This would require
me to set up ffmpeg. Is there a good way to do this?
-- 
-------------
Gautam |


More information about the ffmpeg-devel mailing list