From 2a57c9ae8f39f7023c35e1da8f99267c0440a3a8 Mon Sep 17 00:00:00 2001 From: Georg Lippitsch Date: Fri, 24 Aug 2012 15:24:15 +0200 Subject: [PATCH] dpx: 10 and 12 bit encoding Encode GBRP10 pixel format into 10 bit DPX. Encode GBRP12 pixel format into 12 bit DPX. Signed-off-by: Michael Niedermayer --- libavcodec/dpxenc.c | 71 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 69 insertions(+), 2 deletions(-) diff --git a/libavcodec/dpxenc.c b/libavcodec/dpxenc.c index 09ab14a2e3..451b7b976e 100644 --- a/libavcodec/dpxenc.c +++ b/libavcodec/dpxenc.c @@ -30,6 +30,7 @@ typedef struct DPXContext { int big_endian; int bits_per_component; int descriptor; + int planar; } DPXContext; static av_cold int encode_init(AVCodecContext *avctx) @@ -43,6 +44,7 @@ static av_cold int encode_init(AVCodecContext *avctx) s->big_endian = 1; s->bits_per_component = 8; s->descriptor = 50; /* RGB */ + s->planar = 0; switch (avctx->pix_fmt) { case PIX_FMT_RGB24: @@ -61,6 +63,18 @@ static av_cold int encode_init(AVCodecContext *avctx) s->descriptor = 51; s->bits_per_component = 16; break; + case PIX_FMT_GBRP10LE: + s->big_endian = 0; + case PIX_FMT_GBRP10BE: + s->bits_per_component = 10; + s->planar = 1; + break; + case PIX_FMT_GBRP12LE: + s->big_endian = 0; + case PIX_FMT_GBRP12BE: + s->bits_per_component = 12; + s->planar = 1; + break; default: av_log(avctx, AV_LOG_INFO, "unsupported pixel format\n"); return -1; @@ -106,6 +120,48 @@ static void encode_rgb48_10bit(AVCodecContext *avctx, const AVPicture *pic, uint } } +static void encode_gbrp10(AVCodecContext *avctx, const AVPicture *pic, uint8_t *dst) +{ + DPXContext *s = avctx->priv_data; + const uint8_t *src[3] = {pic->data[0], pic->data[1], pic->data[2]}; + int x, y, i; + + for (y = 0; y < avctx->height; y++) { + for (x = 0; x < avctx->width; x++) { + int value; + if ((avctx->pix_fmt & 1)) { + value = (AV_RB16(src[0] + 2*x) << 12) + | (AV_RB16(src[1] + 2*x) << 2) + | (AV_RB16(src[2] + 2*x) << 22); + } else { + value = (AV_RL16(src[0] + 2*x) << 12) + | (AV_RL16(src[1] + 2*x) << 2) + | (AV_RL16(src[2] + 2*x) << 22); + } + write32(dst, value); + dst += 4; + } + for (i = 0; i < 3; i++) + src[i] += pic->linesize[i]; + } +} + +static void encode_gbrp12(AVCodecContext *avctx, const AVPicture *pic, uint16_t *dst) +{ + const uint16_t *src[3] = {(uint16_t*)pic->data[0], + (uint16_t*)pic->data[1], + (uint16_t*)pic->data[2]}; + int x, y, i; + for (y = 0; y < avctx->height; y++) { + for (x = 0; x < avctx->width; x++) { + for (i = 0; i < 3; i++) + *dst++ = *(src[i] + x); + } + for (i = 0; i < 3; i++) + src[i] += pic->linesize[i]/2; + } +} + static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet) { @@ -143,7 +199,8 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, buf[801] = 2; /* linear transfer */ buf[802] = 2; /* linear colorimetric */ buf[803] = s->bits_per_component; - write16(buf + 804, s->bits_per_component == 10 ? 1 : 0); /* packing method */ + write16(buf + 804, (s->bits_per_component == 10 || s->bits_per_component == 12) ? + 1 : 0); /* packing method */ /* Image source information header */ write32(buf + 1628, avctx->sample_aspect_ratio.num); @@ -159,7 +216,13 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt, return size; break; case 10: - encode_rgb48_10bit(avctx, (const AVPicture*)frame, buf + HEADER_SIZE); + if (s->planar) + encode_gbrp10(avctx, (const AVPicture*)frame, buf + HEADER_SIZE); + else + encode_rgb48_10bit(avctx, (const AVPicture*)frame, buf + HEADER_SIZE); + break; + case 12: + encode_gbrp12(avctx, (const AVPicture*)frame, (uint16_t*)(buf + HEADER_SIZE)); break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported bit depth: %d\n", s->bits_per_component); @@ -190,6 +253,10 @@ AVCodec ff_dpx_encoder = { PIX_FMT_RGB48BE, PIX_FMT_RGBA64LE, PIX_FMT_RGBA64BE, + PIX_FMT_GBRP10LE, + PIX_FMT_GBRP10BE, + PIX_FMT_GBRP12LE, + PIX_FMT_GBRP12BE, PIX_FMT_NONE}, .long_name = NULL_IF_CONFIG_SMALL("DPX image"), };