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 <pie...@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
_______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel