diff mbox

[FFmpeg-devel,v1,1/2] codec: vrawdepay: add decoder for RFC4175

Message ID 20170222201845.r4wc5etnefoxkwvb@workotop.localdomain
State New
Headers show

Commit Message

Damien Riegel Feb. 22, 2017, 8:18 p.m. UTC
On Fri, Feb 17, 2017 at 03:01:05PM -0500, Damien Riegel wrote:
> Hi,
> 
> On Thu, Feb 16, 2017 at 06:19:00PM +0000, Rostislav Pehlivanov wrote:
> > >
> > > No, do this in libavfilter and do not introduce another useless pseudo
> > > codec
> > >
> > 
> > *libavformat, sorry
> 
> The advantage of using a pseudo codec just to depack the stream is that
> the input and the codec are in separate threads in ffmpeg, so it can
> handle a heavier workload.

Please find attached a v2, with the implementation in libavformat. Note
that I don't want to send it as a patch of its own because the
performance issue is not addressed.

Basically, our test case is a raw input stream YUV 4:2:2 10 bits 1080p
at 60fps. With the pseudo-codec, we are able to transcode it to h264 and
dump it to a file. With unpacking done in the libavformat, the input
thread gets too busy and can't stand the load.

In the implementation you made [1] unpacking was done in libavcodec, so
why is it not an acceptable solution for mainline?

[1] https://github.com/funman/ffmpeg-sdi

Thanks,

Comments

Rostislav Pehlivanov Feb. 22, 2017, 9:33 p.m. UTC | #1
On 22 February 2017 at 20:18, Damien Riegel <
damien.riegel@savoirfairelinux.com> wrote:

> On Fri, Feb 17, 2017 at 03:01:05PM -0500, Damien Riegel wrote:
> > Hi,
> >
> > On Thu, Feb 16, 2017 at 06:19:00PM +0000, Rostislav Pehlivanov wrote:
> > > >
> > > > No, do this in libavfilter and do not introduce another useless
> pseudo
> > > > codec
> > > >
> > >
> > > *libavformat, sorry
> >
> > The advantage of using a pseudo codec just to depack the stream is that
> > the input and the codec are in separate threads in ffmpeg, so it can
> > handle a heavier workload.
>
> Please find attached a v2, with the implementation in libavformat. Note
> that I don't want to send it as a patch of its own because the
> performance issue is not addressed.
>
> Basically, our test case is a raw input stream YUV 4:2:2 10 bits 1080p
> at 60fps. With the pseudo-codec, we are able to transcode it to h264 and
> dump it to a file. With unpacking done in the libavformat, the input
> thread gets too busy and can't stand the load.
>
> In the implementation you made [1] unpacking was done in libavcodec, so
> why is it not an acceptable solution for mainline?
>
>
I now think it was ok to have a custom codec format because V210 is
implemented in such a way in lavc. So I think the first version of your
patch was better. You just didn't bother to list a valid reason besides
"offload it to another thread" and I didn't think of V210 at the time.
libavformat has no support for assembly so putting the unpacking there
would be slower too. I suggest posting a v3 of the patch which is like v1
(but please rename the codec name to something better) and which uses the
assembly for unpacking from the repository you linked.

PS: In that repo its _not_ done in lavc and it was never done in lavc, the
point was to use lavc's assembly framework so that if you linked to it and
used the private functions you'd be able to use them _outside_ of lavc.
This was because upipe, which is something made to handle the stinkiest
kind of crap broadcasting people invent because ffmpeg couldn't (and it
absolutely doesn't have to), didn't have any support for assembly.
Eventually support for that was added and everything from the repo plus
more has been implemented there.
Kieran Kunhya Feb. 22, 2017, 10:39 p.m. UTC | #2
On Wed, 22 Feb 2017, 21:39 Rostislav Pehlivanov, <atomnuker@gmail.com>
wrote:

> On 22 February 2017 at 20:18, Damien Riegel <
> damien.riegel@savoirfairelinux.com> wrote:
>
> > On Fri, Feb 17, 2017 at 03:01:05PM -0500, Damien Riegel wrote:
> > > Hi,
> > >
> > > On Thu, Feb 16, 2017 at 06:19:00PM +0000, Rostislav Pehlivanov wrote:
> > > > >
> > > > > No, do this in libavfilter and do not introduce another useless
> > pseudo
> > > > > codec
> > > > >
> > > >
> > > > *libavformat, sorry
> > >
> > > The advantage of using a pseudo codec just to depack the stream is that
> > > the input and the codec are in separate threads in ffmpeg, so it can
> > > handle a heavier workload.
> >
> > Please find attached a v2, with the implementation in libavformat. Note
> > that I don't want to send it as a patch of its own because the
> > performance issue is not addressed.
> >
> > Basically, our test case is a raw input stream YUV 4:2:2 10 bits 1080p
> > at 60fps. With the pseudo-codec, we are able to transcode it to h264 and
> > dump it to a file. With unpacking done in the libavformat, the input
> > thread gets too busy and can't stand the load.
> >
> > In the implementation you made [1] unpacking was done in libavcodec, so
> > why is it not an acceptable solution for mainline?
> >
> >
> I now think it was ok to have a custom codec format because V210 is
> implemented in such a way in lavc. So I think the first version of your
> patch was better. You just didn't bother to list a valid reason besides
> "offload it to another thread" and I didn't think of V210 at the time.
> libavformat has no support for assembly so putting the unpacking there
> would be slower too. I suggest posting a v3 of the patch which is like v1
> (but please rename the codec name to something better) and which uses the
> assembly for unpacking from the repository you linked.
>
> PS: In that repo its _not_ done in lavc and it was never done in lavc, the
> point was to use lavc's assembly framework so that if you linked to it and
> used the private functions you'd be able to use them _outside_ of lavc.
> This was because upipe, which is something made to handle the stinkiest
> kind of crap broadcasting people invent because ffmpeg couldn't (and it
> absolutely doesn't have to), didn't have any support for assembly.
> Eventually support for that was added and everything from the repo plus
> more has been implemented there.
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


Further to what Rostislav said, please mark this as experimental. You're
not going to be able to do more than one stream for architectural reasons
and I don't want people blaming FFmpeg.

Kieran
Damien Riegel Feb. 23, 2017, 5:12 p.m. UTC | #3
On Wed, Feb 22, 2017 at 09:33:03PM +0000, Rostislav Pehlivanov wrote:
> On 22 February 2017 at 20:18, Damien Riegel <
> damien.riegel@savoirfairelinux.com> wrote:
> 
> > On Fri, Feb 17, 2017 at 03:01:05PM -0500, Damien Riegel wrote:
> > > Hi,
> > >
> > > On Thu, Feb 16, 2017 at 06:19:00PM +0000, Rostislav Pehlivanov wrote:
> > > > >
> > > > > No, do this in libavfilter and do not introduce another useless
> > pseudo
> > > > > codec
> > > > >
> > > >
> > > > *libavformat, sorry
> > >
> > > The advantage of using a pseudo codec just to depack the stream is that
> > > the input and the codec are in separate threads in ffmpeg, so it can
> > > handle a heavier workload.
> >
> > Please find attached a v2, with the implementation in libavformat. Note
> > that I don't want to send it as a patch of its own because the
> > performance issue is not addressed.
> >
> > Basically, our test case is a raw input stream YUV 4:2:2 10 bits 1080p
> > at 60fps. With the pseudo-codec, we are able to transcode it to h264 and
> > dump it to a file. With unpacking done in the libavformat, the input
> > thread gets too busy and can't stand the load.
> >
> > In the implementation you made [1] unpacking was done in libavcodec, so
> > why is it not an acceptable solution for mainline?
> >
> >
> I now think it was ok to have a custom codec format because V210 is
> implemented in such a way in lavc. So I think the first version of your
> patch was better. You just didn't bother to list a valid reason besides
> "offload it to another thread" and I didn't think of V210 at the time.
> libavformat has no support for assembly so putting the unpacking there
> would be slower too. I suggest posting a v3 of the patch which is like v1
> (but please rename the codec name to something better) and which uses the
> assembly for unpacking from the repository you linked.

I'll respin a v3 with codec marked as experimental and renamed to
something different. Which name would suit? rfc4175? rtpvideo?

For the assembly, I'd rather send it later as a separate patch, does
that work for you?

Thanks,
Rostislav Pehlivanov Feb. 24, 2017, 6:31 a.m. UTC | #4
On 23 February 2017 at 17:12, Damien Riegel <
damien.riegel@savoirfairelinux.com> wrote:

> On Wed, Feb 22, 2017 at 09:33:03PM +0000, Rostislav Pehlivanov wrote:
> > On 22 February 2017 at 20:18, Damien Riegel <
> > damien.riegel@savoirfairelinux.com> wrote:
> >
> > > On Fri, Feb 17, 2017 at 03:01:05PM -0500, Damien Riegel wrote:
> > > > Hi,
> > > >
> > > > On Thu, Feb 16, 2017 at 06:19:00PM +0000, Rostislav Pehlivanov wrote:
> > > > > >
> > > > > > No, do this in libavfilter and do not introduce another useless
> > > pseudo
> > > > > > codec
> > > > > >
> > > > >
> > > > > *libavformat, sorry
> > > >
> > > > The advantage of using a pseudo codec just to depack the stream is
> that
> > > > the input and the codec are in separate threads in ffmpeg, so it can
> > > > handle a heavier workload.
> > >
> > > Please find attached a v2, with the implementation in libavformat. Note
> > > that I don't want to send it as a patch of its own because the
> > > performance issue is not addressed.
> > >
> > > Basically, our test case is a raw input stream YUV 4:2:2 10 bits 1080p
> > > at 60fps. With the pseudo-codec, we are able to transcode it to h264
> and
> > > dump it to a file. With unpacking done in the libavformat, the input
> > > thread gets too busy and can't stand the load.
> > >
> > > In the implementation you made [1] unpacking was done in libavcodec, so
> > > why is it not an acceptable solution for mainline?
> > >
> > >
> > I now think it was ok to have a custom codec format because V210 is
> > implemented in such a way in lavc. So I think the first version of your
> > patch was better. You just didn't bother to list a valid reason besides
> > "offload it to another thread" and I didn't think of V210 at the time.
> > libavformat has no support for assembly so putting the unpacking there
> > would be slower too. I suggest posting a v3 of the patch which is like v1
> > (but please rename the codec name to something better) and which uses the
> > assembly for unpacking from the repository you linked.
>
> I'll respin a v3 with codec marked as experimental and renamed to
> something different. Which name would suit? rfc4175? rtpvideo?
>
>
I meant the AV_CODEC ID, not the demuxer, rfc4175 is perfectly fine for the
demuxer name.
I think AV_CODEC_ID_BITPACKED would be perfect. Just make sure you populate
the pixel format (e.g. to what the bitpacked should be unpacked to) in the
demuxer, and in the "decoder"/unpacker in libavcodec you just read the
pixfmt that has been set and use an appropriate unpacking function. Also
while you're at it, set everything like framerate, field order, pixel
format, etc. that you can read in the bitstream in the demuxer to allow
ffprobe and others to know what they're getting.
Keep in mind RFC4175 doesn't just support 422 YUV 10bit, LIKE MANY PEOPLE
IN BROADCASTING SEEM TO THINK BECAUSE OBVIOUSLY ITS THE GOD CHOSEN PIXEL
FORMAT, RFC4175 supports 8 bits, 10 bits, 12 bits, 16 bits as well as RGB
at all those bit depths. So for now please return AVERROR_PATCHWELCOME in
the demuxer on any currently unsupported format and please make sure that
in the future the demuxer will be able to be extended to support those
(don't assume its the "god chosen format" like those heathens like to).
Also if the demuxer receives something that isn't bitpacked (e.g. RGB/YUV
at 8 or 16 bits), it should output it directly rather than do a NOOP
"decoding"/unpacking.


For the assembly, I'd rather send it later as a separate patch, does
> that work for you?
>

Yes, that's fine.
Carl Eugen Hoyos April 11, 2018, 6:03 p.m. UTC | #5
2017-02-22 22:33 GMT+01:00, Rostislav Pehlivanov <atomnuker@gmail.com>:
> On 22 February 2017 at 20:18, Damien Riegel <
> damien.riegel@savoirfairelinux.com> wrote:
>
>> On Fri, Feb 17, 2017 at 03:01:05PM -0500, Damien Riegel wrote:
>> > Hi,
>> >
>> > On Thu, Feb 16, 2017 at 06:19:00PM +0000, Rostislav Pehlivanov wrote:
>> > > >
>> > > > No, do this in libavfilter and do not introduce another useless
>> pseudo
>> > > > codec
>> > > >
>> > >
>> > > *libavformat, sorry
>> >
>> > The advantage of using a pseudo codec just to depack the stream is that
>> > the input and the codec are in separate threads in ffmpeg, so it can
>> > handle a heavier workload.
>>
>> Please find attached a v2, with the implementation in libavformat. Note
>> that I don't want to send it as a patch of its own because the
>> performance issue is not addressed.
>>
>> Basically, our test case is a raw input stream YUV 4:2:2 10 bits 1080p
>> at 60fps. With the pseudo-codec, we are able to transcode it to h264 and
>> dump it to a file. With unpacking done in the libavformat, the input
>> thread gets too busy and can't stand the load.
>>
>> In the implementation you made [1] unpacking was done in libavcodec, so
>> why is it not an acceptable solution for mainline?
>>
>>
> I now think it was ok to have a custom codec format because V210 is
> implemented in such a way in lavc.

(Since every time I stumble over "bitpacked" I wonder where this
came from...)

V210 exists in several multimedia containers, so adding a codec
was unavoidable.
I don't think this is true for bitpacked, or is it?

Carl Eugen
diff mbox

Patch

From c81e69979433ed519932354e848889a90d25f1c5 Mon Sep 17 00:00:00 2001
From: Damien Riegel <damien.riegel@savoirfairelinux.com>
Date: Wed, 16 Nov 2016 15:27:13 -0500
Subject: [PATCH v2] rtp: rawvideo: add handler for YCbCr-4:2:2

This adds partial support for the RFC 4175 (raw video over RTP). The
only supported formats are the YCbCr-4:2:2 8 and 10 bit.

For 8-bit depth, the format is similar to AV_PIX_FMT_UYVY422, and for
10-bit, the stream is repacked to the planar format
AV_PIX_FMT_YUV422P10LE.

Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
---
 libavformat/Makefile          |   1 +
 libavformat/rtpdec.c          |   1 +
 libavformat/rtpdec_formats.h  |   1 +
 libavformat/rtpdec_rawvideo.c | 259 ++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 262 insertions(+)
 create mode 100644 libavformat/rtpdec_rawvideo.c

diff --git a/libavformat/Makefile b/libavformat/Makefile
index fc2d76067b..e17ba95c23 100644
--- a/libavformat/Makefile
+++ b/libavformat/Makefile
@@ -55,6 +55,7 @@  OBJS-$(CONFIG_RTPDEC)                    += rdt.o                       \
                                             rtpdec_qcelp.o              \
                                             rtpdec_qdm2.o               \
                                             rtpdec_qt.o                 \
+                                            rtpdec_rawvideo.o           \
                                             rtpdec_svq3.o               \
                                             rtpdec_vc2hq.o              \
                                             rtpdec_vp8.o                \
diff --git a/libavformat/rtpdec.c b/libavformat/rtpdec.c
index 53cdad7396..345318c32c 100644
--- a/libavformat/rtpdec.c
+++ b/libavformat/rtpdec.c
@@ -114,6 +114,7 @@  void ff_register_rtp_dynamic_payload_handlers(void)
     ff_register_dynamic_payload_handler(&ff_qt_rtp_vid_handler);
     ff_register_dynamic_payload_handler(&ff_quicktime_rtp_aud_handler);
     ff_register_dynamic_payload_handler(&ff_quicktime_rtp_vid_handler);
+    ff_register_dynamic_payload_handler(&ff_rawvideo_rtp_handler);
     ff_register_dynamic_payload_handler(&ff_svq3_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_theora_dynamic_handler);
     ff_register_dynamic_payload_handler(&ff_vc2hq_dynamic_handler);
diff --git a/libavformat/rtpdec_formats.h b/libavformat/rtpdec_formats.h
index 3292a3d265..fab12fd139 100644
--- a/libavformat/rtpdec_formats.h
+++ b/libavformat/rtpdec_formats.h
@@ -82,6 +82,7 @@  extern RTPDynamicProtocolHandler ff_qt_rtp_aud_handler;
 extern RTPDynamicProtocolHandler ff_qt_rtp_vid_handler;
 extern RTPDynamicProtocolHandler ff_quicktime_rtp_aud_handler;
 extern RTPDynamicProtocolHandler ff_quicktime_rtp_vid_handler;
+extern RTPDynamicProtocolHandler ff_rawvideo_rtp_handler;
 extern RTPDynamicProtocolHandler ff_svq3_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_theora_dynamic_handler;
 extern RTPDynamicProtocolHandler ff_vc2hq_dynamic_handler;
diff --git a/libavformat/rtpdec_rawvideo.c b/libavformat/rtpdec_rawvideo.c
new file mode 100644
index 0000000000..7edde84306
--- /dev/null
+++ b/libavformat/rtpdec_rawvideo.c
@@ -0,0 +1,259 @@ 
+/*
+ * RTP Depacketization of RAW video (TR-03)
+ * Copyright (c) 2016 Savoir-faire Linux, Inc
+ *
+ * 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
+ */
+
+/* Development sponsored by CBC/Radio-Canada */
+
+#include <libavcodec/get_bits.h>
+#include <libavutil/avstring.h>
+#include <libavutil/imgutils.h>
+#include <libavutil/pixdesc.h>
+#include "avio_internal.h"
+#include "rtpdec_formats.h"
+
+struct PayloadContext {
+    char *sampling;
+    int depth;
+    int width;
+    int height;
+    enum AVPixelFormat pixfmt;
+
+    void *frame;
+    unsigned int frame_size;
+    unsigned int pgroup; /* size of the pixel group in bytes */
+    unsigned int xinc;
+
+    uint32_t timestamp;
+};
+
+static int raw_parse_format(AVStream *stream,
+                            PayloadContext *data)
+{
+    enum AVPixelFormat pixfmt = AV_PIX_FMT_NONE;
+    int tag = 0;
+
+    if (!strcmp(data->sampling, "YCbCr-4:2:2")) {
+        data->xinc = 2;
+
+        if (data->depth == 8) {
+            tag = MKTAG('U', 'Y', 'V', 'Y');
+            data->pgroup = 4;
+            pixfmt = AV_PIX_FMT_UYVY422;
+        } else if (data->depth == 10) {
+            tag = MKTAG('I', '2', 'A', 'L');
+            data->pgroup = 5;
+            pixfmt = AV_PIX_FMT_YUV422P10;
+        } else {
+            return -1;
+        }
+
+        stream->codecpar->bits_per_coded_sample = data->depth * 2;
+    } else {
+        return -1;
+    }
+
+    stream->codecpar->codec_tag = tag;
+    stream->codecpar->field_order = AV_FIELD_PROGRESSIVE;
+    data->frame_size = av_image_get_buffer_size(pixfmt, data->width, data->height, 1);
+    data->pixfmt = pixfmt;
+
+    return 0;
+}
+
+static int raw_parse_fmtp(AVFormatContext *s, AVStream *stream,
+                          PayloadContext *data, const char *attr,
+                          const char *value)
+{
+    if (!strcmp(attr, "width"))
+        data->width = atoi(value);
+    else if (!strcmp(attr, "height"))
+        data->height = atoi(value);
+    else if (!strcmp(attr, "sampling"))
+        data->sampling = av_strdup(value);
+    else if (!strcmp(attr, "depth"))
+        data->depth = atoi(value);
+
+    return 0;
+}
+
+static int raw_parse_sdp_line(AVFormatContext *s, int st_index,
+                              PayloadContext *data, const char *line)
+{
+    const char *p;
+
+    if (st_index < 0)
+        return 0;
+
+    if (av_strstart(line, "fmtp:", &p)) {
+        AVStream *stream = s->streams[st_index];
+        int ret = ff_parse_fmtp(s, stream, data, p, raw_parse_fmtp);
+
+        if (ret < 0)
+            return ret;
+
+
+        if (!data->sampling || !data->depth || !data->width || !data->height)
+            return -1;
+
+        stream->codecpar->width = data->width;
+        stream->codecpar->height = data->height;
+
+        ret = raw_parse_format(stream, data);
+        av_freep(&data->sampling);
+
+        return ret;
+    }
+
+    return 0;
+}
+
+static int raw_finalize_packet(PayloadContext *data, AVPacket *pkt,
+                               int stream_index)
+{
+   int ret;
+
+   pkt->stream_index = stream_index;
+   ret = av_packet_from_data(pkt, data->frame, data->frame_size);
+   if (ret < 0) {
+       av_freep(&data->frame);
+   }
+
+   data->frame = NULL;
+
+   return ret;
+}
+
+static int raw_handle_packet(AVFormatContext *ctx, PayloadContext *data,
+                             AVStream *st, AVPacket *pkt, uint32_t *timestamp,
+                             const uint8_t * buf, int len,
+                             uint16_t seq, int flags)
+{
+    int length, line, offset, cont;
+    const uint8_t *headers = buf + 2; /* skip extended seqnum */
+    const uint8_t *payload = buf + 2;
+    int payload_len = len - 2;
+    int missed_last_packet = 0;
+
+    if (*timestamp != data->timestamp) {
+        if (data->frame) {
+            /*
+             * if we're here, it means that two RTP packets didn't have the
+             * same timestamp, which is a sign that they were packets from two
+             * different frames, but we didn't get the flag RTP_FLAG_MARKER on
+             * the first one of these frames (last packet of a frame).
+             * Finalize the previous frame anyway by filling the AVPacket.
+             */
+            av_log(ctx, AV_LOG_ERROR, "Missed previous RTP Marker\n");
+            missed_last_packet = 1;
+            raw_finalize_packet(data, pkt, st->index);
+        }
+
+        data->timestamp = *timestamp;
+
+        data->frame = av_malloc(data->frame_size);
+        if (!data->frame) {
+            av_log(ctx, AV_LOG_ERROR, "Out of memory.\n");
+            return AVERROR(ENOMEM);
+        }
+    }
+
+    /*
+     * looks for the 'Continuation bit' in scan lines' headers
+     * to find where data start
+     */
+    do {
+        if (payload_len < 6)
+            return AVERROR_INVALIDDATA;
+
+        cont = payload[4] & 0x80;
+        payload += 6;
+        payload_len -= 6;
+    } while (cont);
+
+    /* and now iterate over every scan lines */
+    do {
+        if (payload_len < data->pgroup)
+            return AVERROR_INVALIDDATA;
+
+        length = (headers[0] << 8) | headers[1];
+        line = ((headers[2] & 0x7f) << 8) | headers[3];
+        offset = ((headers[4] & 0x7f) << 8) | headers[5];
+        cont = headers[4] & 0x80;
+        headers += 6;
+
+        if (length % data->pgroup)
+            return AVERROR_INVALIDDATA;
+
+        if (length > payload_len)
+            length = payload_len;
+
+        if (data->depth == 8) {
+           uint8_t *dest = data->frame;
+
+           dest += (line * data->width + offset) * data->pgroup / data->xinc;
+           memcpy(dest, payload, length);
+        }
+        else if (data->depth == 10) {
+            uint16_t *y, *u, *v;
+            GetBitContext bc;
+            int i, ret;
+
+            uint8_t* plans[4];
+            int linesizes[4];
+
+            av_image_fill_arrays(plans, linesizes, data->frame, data->pixfmt,
+                                 data->width, data->height, 2);
+            y = (uint16_t*)(plans[0] + (line * data->width + offset) * 2);
+            u = (uint16_t*)(plans[1] + line * data->width + offset);
+            v = (uint16_t*)(plans[2] + line * data->width + offset);
+
+            ret = init_get_bits(&bc, payload, length * 8);
+            if (ret)
+               return ret;
+
+            for (i = 0; i < length / data->pgroup; i++) {
+               *u++ = get_bits(&bc, 10);
+               *y++ = get_bits(&bc, 10);
+               *v++ = get_bits(&bc, 10);
+               *y++ = get_bits(&bc, 10);
+            }
+        }
+
+        payload += length;
+        payload_len -= length;
+    } while (cont);
+
+    if ((flags & RTP_FLAG_MARKER)) {
+        return raw_finalize_packet(data, pkt, st->index);
+    } else if (missed_last_packet) {
+        return 0;
+    }
+
+    return AVERROR(EAGAIN);
+}
+
+RTPDynamicProtocolHandler ff_rawvideo_rtp_handler = {
+    .enc_name           = "raw",
+    .codec_type         = AVMEDIA_TYPE_VIDEO,
+    .codec_id           = AV_CODEC_ID_RAWVIDEO,
+    .priv_data_size     = sizeof(PayloadContext),
+    .parse_sdp_a_line   = raw_parse_sdp_line,
+    .parse_packet       = raw_handle_packet,
+};
-- 
2.11.1