diff mbox series

[FFmpeg-devel,v2,05/12] avformat/rtpenc: adds partial support for the RFC 4175

Message ID 1637066968-4697-1-git-send-email-lance.lmwang@gmail.com
State New
Headers show
Series None | expand

Commit Message

Lance Wang Nov. 16, 2021, 12:49 p.m. UTC
From: Limin Wang <lance.lmwang@gmail.com>

Signed-off-by: Limin Wang <lance.lmwang@gmail.com>
---
 Changelog                    |   1 +
 libavformat/Makefile         |   1 +
 libavformat/rtpenc.c         |   4 ++
 libavformat/rtpenc.h         |   1 +
 libavformat/rtpenc_rfc4175.c | 116 +++++++++++++++++++++++++++++++++++
 libavformat/sdp.c            |  25 ++++++++
 libavformat/version.h        |   2 +-
 7 files changed, 149 insertions(+), 1 deletion(-)
 create mode 100644 libavformat/rtpenc_rfc4175.c
diff mbox series

Patch

diff --git a/Changelog b/Changelog
index 765ec82915..4fecc5b9d0 100644
--- a/Changelog
+++ b/Changelog
@@ -30,6 +30,7 @@  version <next>:
 - xcorrelate video filter
 - varblur video filter
 - huesaturation video filter
+- RTP packetizer for uncompressed video (RFC rfc4175)
 
 
 version 4.4:
diff --git a/libavformat/Makefile b/libavformat/Makefile
index 3d6c8ef8f5..a19d2e0c88 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -482,6 +482,7 @@  OBJS-$(CONFIG_RTP_MUXER)                 += rtp.o         \
                                             rtpenc_jpeg.o \
                                             rtpenc_mpv.o     \
                                             rtpenc.o      \
+                                            rtpenc_rfc4175.o    \
                                             rtpenc_vc2hq.o              \
                                             rtpenc_vp8.o  \
                                             rtpenc_vp9.o                \
diff --git a/libavformat/rtpenc.c b/libavformat/rtpenc.c
index 2a1c176066..4f115cc77e 100644
--- a/libavformat/rtpenc.c
+++ b/libavformat/rtpenc.c
@@ -84,6 +84,7 @@  static int is_supported(enum AVCodecID id)
     case AV_CODEC_ID_MJPEG:
     case AV_CODEC_ID_SPEEX:
     case AV_CODEC_ID_OPUS:
+    case AV_CODEC_ID_RAWVIDEO:
         return 1;
     default:
         return 0;
@@ -619,6 +620,9 @@  static int rtp_write_packet(AVFormatContext *s1, AVPacket *pkt)
     case AV_CODEC_ID_MJPEG:
         ff_rtp_send_jpeg(s1, pkt->data, size);
         break;
+    case AV_CODEC_ID_RAWVIDEO:
+        ff_rtp_send_raw_rfc4175 (s1, pkt->data, size);
+        break;
     case AV_CODEC_ID_OPUS:
         if (size > s->max_payload_size) {
             av_log(s1, AV_LOG_ERROR,
diff --git a/libavformat/rtpenc.h b/libavformat/rtpenc.h
index 62dc9ab10a..70ea85bf3f 100644
--- a/libavformat/rtpenc.h
+++ b/libavformat/rtpenc.h
@@ -95,6 +95,7 @@  void ff_rtp_send_vc2hq(AVFormatContext *s1, const uint8_t *buf, int size, int in
 void ff_rtp_send_vp8(AVFormatContext *s1, const uint8_t *buff, int size);
 void ff_rtp_send_vp9(AVFormatContext *s1, const uint8_t *buff, int size);
 void ff_rtp_send_jpeg(AVFormatContext *s1, const uint8_t *buff, int size);
+void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size);
 
 const uint8_t *ff_h263_find_resync_marker_reverse(const uint8_t *av_restrict start,
                                                   const uint8_t *av_restrict end);
diff --git a/libavformat/rtpenc_rfc4175.c b/libavformat/rtpenc_rfc4175.c
new file mode 100644
index 0000000000..6fa34b64cb
--- /dev/null
+++ b/libavformat/rtpenc_rfc4175.c
@@ -0,0 +1,116 @@ 
+/*
+ * RTP Packetization of RAW video (RFC4175)
+ * Copyright (c) 2021 Limin Wang
+ *
+ * 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
+ */
+#include "avformat.h"
+#include "rtpenc.h"
+
+void ff_rtp_send_raw_rfc4175(AVFormatContext *s1, const uint8_t *buf, int size)
+{
+    RTPMuxContext *s = s1->priv_data;
+    int width = s1->streams[0]->codecpar->width;
+    int height = s1->streams[0]->codecpar->height;
+    int xinc, yinc, pgroup;
+    int field = 0;
+    int i = 0;
+    int offset = 0;
+
+    s->timestamp = s->cur_timestamp;
+    switch (s1->streams[0]->codecpar->format) {
+        case AV_PIX_FMT_UYVY422:
+            xinc = yinc = 2;
+            pgroup = 4;
+            break;
+        case AV_PIX_FMT_YUV420P:
+            xinc = yinc = 4;
+            pgroup = 6;
+            break;
+        default:
+            return;
+    }
+
+    while (i < height) {
+        int left = s->max_payload_size;
+        uint8_t *dest = s->buf;
+        uint8_t *headers;
+        const int head_size = 6;
+        int next_line;
+        int length, cont, pixels;
+
+        /* Extended Sequence Number */
+        *dest++ = 0;
+        *dest++ = 0;
+        left   -= 2;
+
+        headers = dest;
+        do {
+            pixels = width * xinc - offset;
+            length = (pixels * pgroup) / xinc;
+
+            left -= head_size;
+            if (left >= length) {
+                next_line = 1;
+            } else {
+                pixels = (left / pgroup) * xinc;
+                length = (pixels * pgroup) / xinc;
+                next_line = 0;
+            }
+            left -= length;
+
+            /* Length */
+            *dest++ = (length >> 8) & 0xff;
+            *dest++ = length & 0xff;
+
+            /* Line No */
+            *dest++ = ((i >> 8) & 0x7f) | ((field << 7) & 0x80);
+            *dest++ = i & 0xff;
+            if (next_line) i += yinc;
+
+            cont = (left > (head_size + pgroup) && i < height) ? 0x80 : 0x00;
+            /* Offset and Continuation marker */
+            *dest++ = ((offset >> 8) & 0x7f) | cont;
+            *dest++ = offset & 0xff;
+
+            if (next_line)
+                offset  = 0;
+            else
+                offset += pixels;
+        } while (cont);
+
+        do {
+            int l_line;
+            int l_off;
+            int copy_offset;
+
+            length    = (headers[0] << 8) | headers[1];
+            l_line    = ((headers[2] & 0x7f) << 8) | headers[3];
+            l_off     = ((headers[4] & 0x7f) << 8) | headers[5];
+            cont      = headers[4] & 0x80;
+            headers  += head_size;
+
+            copy_offset = (l_line * width + l_off) * pgroup / xinc;
+            if (copy_offset + length > size)
+                break;
+            memcpy (dest, buf + copy_offset, length);
+            dest += length;
+        } while (cont);
+
+        ff_rtp_send_data (s1, s->buf, s->max_payload_size - left, i >= height);
+    }
+}
diff --git a/libavformat/sdp.c b/libavformat/sdp.c
index 1200e553f9..cc04d70c0d 100644
--- a/libavformat/sdp.c
+++ b/libavformat/sdp.c
@@ -660,6 +660,31 @@  static char *sdp_write_media_attributes(char *buff, int size, AVStream *st, int
                                     p->width, p->height, pix_fmt, config);
             break;
         }
+        case AV_CODEC_ID_RAWVIDEO: {
+            const char *pix_fmt;
+            int bit_depth = 8;
+
+            switch (p->format) {
+            case AV_PIX_FMT_UYVY422:
+                pix_fmt = "YCbCr-4:2:2";
+                break;
+            case AV_PIX_FMT_YUV420P:
+                pix_fmt = "YCbCr-4:2:0";
+                break;
+            default:
+                av_log(fmt, AV_LOG_ERROR, "Unsupported pixel format.\n");
+                return NULL;
+            }
+
+            av_strlcatf(buff, size, "a=rtpmap:%d raw/90000\r\n"
+                                    "a=fmtp:%d sampling=%s; "
+                                    "width=%d; height=%d; "
+                                    "depth=%d\r\n",
+                                    payload_type, payload_type,
+                                    pix_fmt, p->width, p->height, bit_depth);
+            break;
+        }
+
         case AV_CODEC_ID_VP8:
             av_strlcatf(buff, size, "a=rtpmap:%d VP8/90000\r\n",
                                      payload_type);
diff --git a/libavformat/version.h b/libavformat/version.h
index 81ed517609..0f76f50892 100644
--- a/libavformat/version.h
+++ b/libavformat/version.h
@@ -33,7 +33,7 @@ 
 // Also please add any ticket numbers that you believe might be affected here
 #define LIBAVFORMAT_VERSION_MAJOR  59
 #define LIBAVFORMAT_VERSION_MINOR   8
-#define LIBAVFORMAT_VERSION_MICRO 100
+#define LIBAVFORMAT_VERSION_MICRO 101
 
 #define LIBAVFORMAT_VERSION_INT AV_VERSION_INT(LIBAVFORMAT_VERSION_MAJOR, \
                                                LIBAVFORMAT_VERSION_MINOR, \