[FFmpeg-devel] patch for ticket #7053
Pierre Chatelier
pierre at chachatelier.fr
Mon Mar 5 15:04:25 EET 2018
Here is a patch proposition for https://trac.ffmpeg.org/ticket/7053
Pierre Chatelier
-------------- next part --------------
From 7cbc1bd47fb97e3498d92eda9c84144de2c06d01 Mon Sep 17 00:00:00 2001
From: Pierre Chatelier <pierre at 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(-)
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;
}
--
2.16.2
More information about the ffmpeg-devel
mailing list