From 039291b0b3c43949f69b2d5b88c08c7c920f261d Mon Sep 17 00:00:00 2001
From: Pierre Chatelier <pierre@chachatelier.fr>
Date: Fri, 2 Mar 2018 16:42:38 +0100
Subject: [PATCH 1/1] added 12, 14, 16 bit depth variatiosn to YUV422 packed
 modes of bitpacked codec

---
 libavcodec/bitpacked.c       | 126 +++++++++++++++++++++++++++++++++++++++++++
 libavformat/rtpdec_rfc4175.c |  12 +++++
 2 files changed, 138 insertions(+)

diff --git a/libavcodec/bitpacked.c b/libavcodec/bitpacked.c
index f0b417d595..caecabc366 100644
--- a/libavcodec/bitpacked.c
+++ b/libavcodec/bitpacked.c
@@ -94,6 +94,123 @@ static int bitpacked_decode_yuv422p10(AVCodecContext *avctx, AVFrame *frame,
     return 0;
 }
 
+static int bitpacked_decode_yuv422p12(AVCodecContext *avctx, AVFrame *frame,
+                                      AVPacket *avpkt)
+{
+    uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 24;
+    uint64_t packet_size = (uint64_t)avpkt->size * 8;
+    GetBitContext bc;
+    uint16_t *y, *u, *v;
+    int ret, i, j;
+
+    ret = ff_get_buffer(avctx, frame, 0);
+    if (ret < 0)
+        return ret;
+
+    if (frame_size > packet_size)
+        return AVERROR_INVALIDDATA;
+
+    if (avctx->width % 2)
+        return AVERROR_PATCHWELCOME;
+
+    ret = init_get_bits(&bc, avpkt->data, avctx->width * avctx->height * 24);
+    if (ret)
+        return ret;
+
+    for (i = 0; i < avctx->height; i++) {
+        y = (uint16_t*)(frame->data[0] + i * frame->linesize[0]);
+        u = (uint16_t*)(frame->data[1] + i * frame->linesize[1]);
+        v = (uint16_t*)(frame->data[2] + i * frame->linesize[2]);
+
+        for (j = 0; j < avctx->width; j += 2) {
+            *u++ = get_bits(&bc, 12);
+            *y++ = get_bits(&bc, 12);
+            *v++ = get_bits(&bc, 12);
+            *y++ = get_bits(&bc, 12);
+        }
+    }
+
+    return 0;
+}
+
+static int bitpacked_decode_yuv422p14(AVCodecContext *avctx, AVFrame *frame,
+                                      AVPacket *avpkt)
+{
+    uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 28;
+    uint64_t packet_size = (uint64_t)avpkt->size * 8;
+    GetBitContext bc;
+    uint16_t *y, *u, *v;
+    int ret, i, j;
+
+    ret = ff_get_buffer(avctx, frame, 0);
+    if (ret < 0)
+        return ret;
+
+    if (frame_size > packet_size)
+        return AVERROR_INVALIDDATA;
+
+    if (avctx->width % 2)
+        return AVERROR_PATCHWELCOME;
+
+    ret = init_get_bits(&bc, avpkt->data, avctx->width * avctx->height * 28);
+    if (ret)
+        return ret;
+
+    for (i = 0; i < avctx->height; i++) {
+        y = (uint16_t*)(frame->data[0] + i * frame->linesize[0]);
+        u = (uint16_t*)(frame->data[1] + i * frame->linesize[1]);
+        v = (uint16_t*)(frame->data[2] + i * frame->linesize[2]);
+
+        for (j = 0; j < avctx->width; j += 2) {
+            *u++ = get_bits(&bc, 14);
+            *y++ = get_bits(&bc, 14);
+            *v++ = get_bits(&bc, 14);
+            *y++ = get_bits(&bc, 14);
+        }
+    }
+
+    return 0;
+}
+
+static int bitpacked_decode_yuv422p16(AVCodecContext *avctx, AVFrame *frame,
+                                      AVPacket *avpkt)
+{
+    uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 32;
+    uint64_t packet_size = (uint64_t)avpkt->size * 8;
+    GetBitContext bc;
+    uint16_t *y, *u, *v;
+    int ret, i, j;
+
+    ret = ff_get_buffer(avctx, frame, 0);
+    if (ret < 0)
+        return ret;
+
+    if (frame_size > packet_size)
+        return AVERROR_INVALIDDATA;
+
+    if (avctx->width % 2)
+        return AVERROR_PATCHWELCOME;
+
+    ret = init_get_bits(&bc, avpkt->data, avctx->width * avctx->height * 32);
+    if (ret)
+        return ret;
+
+    for (i = 0; i < avctx->height; i++) {
+        y = (uint16_t*)(frame->data[0] + i * frame->linesize[0]);
+        u = (uint16_t*)(frame->data[1] + i * frame->linesize[1]);
+        v = (uint16_t*)(frame->data[2] + i * frame->linesize[2]);
+
+        for (j = 0; j < avctx->width; j += 2) {
+            *u++ = get_bits(&bc, 16);
+            *y++ = get_bits(&bc, 16);
+            *v++ = get_bits(&bc, 16);
+            *y++ = get_bits(&bc, 16);
+        }
+    }
+
+    return 0;
+}
+
 static av_cold int bitpacked_init_decoder(AVCodecContext *avctx)
 {
     struct BitpackedContext *bc = avctx->priv_data;
@@ -108,6 +225,15 @@ static av_cold int bitpacked_init_decoder(AVCodecContext *avctx)
         else if (avctx->bits_per_coded_sample == 20 &&
                  avctx->pix_fmt == AV_PIX_FMT_YUV422P10)
             bc->decode = bitpacked_decode_yuv422p10;
+        else if (avctx->bits_per_coded_sample == 24 &&
+                 avctx->pix_fmt == AV_PIX_FMT_YUV422P12)
+            bc->decode = bitpacked_decode_yuv422p12;
+        else if (avctx->bits_per_coded_sample == 28 &&
+                 avctx->pix_fmt == AV_PIX_FMT_YUV422P14)
+            bc->decode = bitpacked_decode_yuv422p14;
+        else if (avctx->bits_per_coded_sample == 32 &&
+                 avctx->pix_fmt == AV_PIX_FMT_YUV422P16)
+            bc->decode = bitpacked_decode_yuv422p16;
         else
             return AVERROR_INVALIDDATA;
     } else {
diff --git a/libavformat/rtpdec_rfc4175.c b/libavformat/rtpdec_rfc4175.c
index 498381dfd3..0fc1a40906 100644
--- a/libavformat/rtpdec_rfc4175.c
+++ b/libavformat/rtpdec_rfc4175.c
@@ -58,6 +58,18 @@ static int rfc4175_parse_format(AVStream *stream, PayloadContext *data)
             data->pgroup = 5;
             bits_per_sample = 20;
             pixfmt = AV_PIX_FMT_YUV422P10;
+        } else if (data->depth == 12) {
+            data->pgroup = 6;
+            bits_per_sample = 24;
+            pixfmt = AV_PIX_FMT_YUV422P12;
+        } else if (data->depth == 14) {
+            data->pgroup = 7;
+            bits_per_sample = 28;
+            pixfmt = AV_PIX_FMT_YUV422P14;
+        } else if (data->depth == 16) {
+            data->pgroup = 8;
+            bits_per_sample = 32;
+            pixfmt = AV_PIX_FMT_YUV422P16;
         } else {
             return AVERROR_INVALIDDATA;
         }
-- 
2.16.2

