diff mbox

[FFmpeg-devel] patch for ticket #7053

Message ID b927f14f-7d6c-1fc7-7bde-c840070b8e48@chachatelier.fr
State New
Headers show

Commit Message

Pierre Chatelier March 5, 2018, 1:04 p.m. UTC
Here is a patch proposition for https://trac.ffmpeg.org/ticket/7053

Pierre Chatelier
From 7cbc1bd47fb97e3498d92eda9c84144de2c06d01 Mon Sep 17 00:00:00 2001
From: Pierre Chatelier <pierre@chachatelier.fr>
Date: Mon, 5 Mar 2018 13:57:00 +0100
Subject: [PATCH 1/1] added YUV422-12, -14, -16 bit depth, mono-8, -10, -12,
 -16 bit depth, rgb888 to bitpacked codec

---
 libavcodec/bitpacked.c       | 281 ++++++++++++++++++++++++++++++++++++++++++-
 libavformat/rtpdec_rfc4175.c |  51 +++++++-
 2 files changed, 330 insertions(+), 2 deletions(-)

Comments

Rostislav Pehlivanov March 5, 2018, 8:32 p.m. UTC | #1
On 5 March 2018 at 13:04, Pierre Chatelier <pierre@chachatelier.fr> wrote:

> Here is a patch proposition for https://trac.ffmpeg.org/ticket/7053
>
> Pierre Chatelier
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
>
No, you need to template it with macros. No point in having hundreds of
duplicated lines.
diff mbox

Patch

diff --git a/libavcodec/bitpacked.c b/libavcodec/bitpacked.c
index f0b417d595..cf6275d963 100644
--- a/libavcodec/bitpacked.c
+++ b/libavcodec/bitpacked.c
@@ -55,6 +55,141 @@  static int bitpacked_decode_uyvy422(AVCodecContext *avctx, AVFrame *frame,
     return 0;
 }
 
+static int bitpacked_decode_gray8(AVCodecContext *avctx, AVFrame *frame,
+                                  AVPacket *avpkt)
+{
+    int ret;
+
+    /* there is no need to copy as the data already match
+     * a known pixel format */
+    frame->buf[0] = av_buffer_ref(avpkt->buf);
+    ret = av_image_fill_arrays(frame->data, frame->linesize, avpkt->data,
+                               avctx->pix_fmt, avctx->width, avctx->height, 1);
+    if (ret < 0) {
+        av_buffer_unref(&frame->buf[0]);
+        return ret;
+    }
+
+    return 0;
+}
+
+static int bitpacked_decode_gray10(AVCodecContext *avctx, AVFrame *frame,
+                                   AVPacket *avpkt)
+{
+    uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 10;
+    uint64_t packet_size = (uint64_t)avpkt->size * 8;
+    GetBitContext bc;
+    uint16_t *g;
+    int ret, i, j;
+    
+    ret = ff_get_buffer(avctx, frame, 0);
+    if (ret < 0)
+        return ret;
+
+    if (frame_size > packet_size)
+        return AVERROR_INVALIDDATA;
+
+    ret = init_get_bits(&bc, avpkt->data, avctx->width * avctx->height * 10);
+    if (ret)
+        return ret;
+
+    for (i = 0; i < avctx->height; i++) {
+        g = (uint16_t*)(frame->data[0] + i * frame->linesize[0]);
+
+        for (j = 0; j < avctx->width; j += 4)
+        {
+          *g++ = get_bits(&bc, 10);
+          *g++ = get_bits(&bc, 10);
+          *g++ = get_bits(&bc, 10);
+          *g++ = get_bits(&bc, 10);
+        }
+    }
+    
+
+    return 0;
+}
+
+static int bitpacked_decode_gray12(AVCodecContext *avctx, AVFrame *frame,
+                                   AVPacket *avpkt)
+{
+    uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 12;
+    uint64_t packet_size = (uint64_t)avpkt->size * 8;
+    GetBitContext bc;
+    uint16_t *g;
+    int ret, i, j;
+
+    ret = ff_get_buffer(avctx, frame, 0);
+    if (ret < 0)
+        return ret;
+
+    if (frame_size > packet_size)
+        return AVERROR_INVALIDDATA;
+
+    ret = init_get_bits(&bc, avpkt->data, avctx->width * avctx->height * 12);
+    if (ret)
+        return ret;
+
+    for (i = 0; i < avctx->height; i++) {
+        g = (uint16_t*)(frame->data[0] + i * frame->linesize[0]);
+
+        for (j = 0; j < avctx->width; j += 2)
+        {
+          *g++ = get_bits(&bc, 12);
+          *g++ = get_bits(&bc, 12);
+        }
+    }
+
+    return 0;
+}
+
+static int bitpacked_decode_gray16(AVCodecContext *avctx, AVFrame *frame,
+                                   AVPacket *avpkt)
+{
+    uint64_t frame_size = (uint64_t)avctx->width * (uint64_t)avctx->height * 16;
+    uint64_t packet_size = (uint64_t)avpkt->size * 8;
+    GetBitContext bc;
+    uint16_t *g;
+    int ret, i, j;
+
+    ret = ff_get_buffer(avctx, frame, 0);
+    if (ret < 0)
+        return ret;
+
+    if (frame_size > packet_size)
+        return AVERROR_INVALIDDATA;
+
+    ret = init_get_bits(&bc, avpkt->data, avctx->width * avctx->height * 16);
+    if (ret)
+        return ret;
+
+    for (i = 0; i < avctx->height; i++) {
+        g = (uint16_t*)(frame->data[0] + i * frame->linesize[0]);
+
+        for (j = 0; j < avctx->width; j++)
+            *g++ = get_bits(&bc, 16);
+    }
+
+    return 0;
+}
+
+static int bitpacked_decode_rgb24(AVCodecContext *avctx, AVFrame *frame,
+                                  AVPacket *avpkt)
+{
+    int ret;
+
+    /* there is no need to copy as the data already match
+     * a known pixel format */
+    frame->buf[0] = av_buffer_ref(avpkt->buf);
+    ret = av_image_fill_arrays(frame->data, frame->linesize, avpkt->data,
+                               avctx->pix_fmt, avctx->width, avctx->height, 1);
+    if (ret < 0) {
+        av_buffer_unref(&frame->buf[0]);
+        return ret;
+    }
+
+    return 0;
+}
+
 static int bitpacked_decode_yuv422p10(AVCodecContext *avctx, AVFrame *frame,
                                       AVPacket *avpkt)
 {
@@ -94,6 +229,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;
@@ -101,13 +353,40 @@  static av_cold int bitpacked_init_decoder(AVCodecContext *avctx)
     if (!avctx->codec_tag || !avctx->width || !avctx->height)
         return AVERROR_INVALIDDATA;
 
-    if (avctx->codec_tag == MKTAG('U', 'Y', 'V', 'Y')) {
+    if (avctx->codec_tag == MKTAG('r', 'a', 'w', ' ')) {
+        if (avctx->bits_per_coded_sample == 8 &&
+            avctx->pix_fmt == AV_PIX_FMT_GRAY8)
+            bc->decode = bitpacked_decode_gray8;
+        else if (avctx->bits_per_coded_sample == 10 &&
+                 avctx->pix_fmt == AV_PIX_FMT_GRAY10)
+            bc->decode = bitpacked_decode_gray10;
+        else if (avctx->bits_per_coded_sample == 12 &&
+                 avctx->pix_fmt == AV_PIX_FMT_GRAY12)
+            bc->decode = bitpacked_decode_gray12;
+        else if (avctx->bits_per_coded_sample == 16 &&
+                 avctx->pix_fmt == AV_PIX_FMT_GRAY16)
+            bc->decode = bitpacked_decode_gray16;
+        else if (avctx->bits_per_coded_sample == 24 &&
+                 avctx->pix_fmt == AV_PIX_FMT_RGB24)
+            bc->decode = bitpacked_decode_rgb24;
+        else
+            return AVERROR_INVALIDDATA;
+    } else if (avctx->codec_tag == MKTAG('U', 'Y', 'V', 'Y')) {
         if (avctx->bits_per_coded_sample == 16 &&
             avctx->pix_fmt == AV_PIX_FMT_UYVY422)
             bc->decode = bitpacked_decode_uyvy422;
         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..fda0023b15 100644
--- a/libavformat/rtpdec_rfc4175.c
+++ b/libavformat/rtpdec_rfc4175.c
@@ -45,8 +45,45 @@  static int rfc4175_parse_format(AVStream *stream, PayloadContext *data)
     enum AVPixelFormat pixfmt = AV_PIX_FMT_NONE;
     int bits_per_sample = 0;
     int tag = 0;
+    
+    if (!strncmp(data->sampling, "Mono", 4)) {
+        tag = MKTAG('r', 'a', 'w', ' ');
 
-    if (!strncmp(data->sampling, "YCbCr-4:2:2", 11)) {
+        if (data->depth == 8) {
+            data->xinc = 1;
+            data->pgroup = 1;
+            bits_per_sample = 8;
+            pixfmt = AV_PIX_FMT_GRAY8;
+        }else if (data->depth == 10) {
+            data->xinc = 4;
+            data->pgroup = 5;
+            bits_per_sample = 10;
+            pixfmt = AV_PIX_FMT_GRAY10;
+        } else if (data->depth == 12) {
+            data->xinc = 2;
+            data->pgroup = 3;
+            bits_per_sample = 12;
+            pixfmt = AV_PIX_FMT_GRAY12;
+        } else if (data->depth == 16) {
+            data->xinc = 1;
+            data->pgroup = 2;
+            bits_per_sample = 16;
+            pixfmt = AV_PIX_FMT_GRAY16;
+        } else {
+            return AVERROR_INVALIDDATA;
+        }
+    } else if (!strncmp(data->sampling, "RGB", 3)) {
+        tag = MKTAG('r', 'a', 'w', ' ');
+        data->xinc = 1;
+
+        if (data->depth == 8) {
+            data->pgroup = 3;
+            bits_per_sample = 24;
+            pixfmt = AV_PIX_FMT_RGB24;
+        } else {
+            return AVERROR_INVALIDDATA;
+        }
+    } else if (!strncmp(data->sampling, "YCbCr-4:2:2", 11)) {
         tag = MKTAG('U', 'Y', 'V', 'Y');
         data->xinc = 2;
 
@@ -58,6 +95,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;
         }