diff options
author | Paul B Mahol <onemda@gmail.com> | 2022-07-01 10:06:15 +0200 |
---|---|---|
committer | Paul B Mahol <onemda@gmail.com> | 2022-07-03 15:16:31 +0200 |
commit | ff1450e449f848ad4b37b3cf448315ba4581364e (patch) | |
tree | 4c6e245afa51c3ec58bb0865ed27f2940acf4f4a /libavcodec/pnmdec.c | |
parent | 33fe3b73c2d4dec674509de5dc48698895f0806b (diff) |
avcodec: add PHM decoder and encoder
Diffstat (limited to 'libavcodec/pnmdec.c')
-rw-r--r-- | libavcodec/pnmdec.c | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c index f2d9b7e4b6..bb2ce53496 100644 --- a/libavcodec/pnmdec.c +++ b/libavcodec/pnmdec.c @@ -26,6 +26,7 @@ #include "internal.h" #include "put_bits.h" #include "pnm.h" +#include "half2float.h" static void samplecpy(uint8_t *dst, const uint8_t *src, int n, int maxval) { @@ -258,6 +259,7 @@ static int pnm_decode_frame(AVCodecContext *avctx, AVFrame *p, } break; case AV_PIX_FMT_GBRPF32: + if (!s->half) { if (avctx->width * avctx->height * 12 > s->bytestream_end - s->bytestream) return AVERROR_INVALIDDATA; scale = 1.f / s->scale; @@ -298,8 +300,68 @@ static int pnm_decode_frame(AVCodecContext *avctx, AVFrame *p, b += p->linesize[1] / 4; } } + } else { + if (avctx->width * avctx->height * 6 > s->bytestream_end - s->bytestream) + return AVERROR_INVALIDDATA; + scale = 1.f / s->scale; + if (s->endian) { + float *r, *g, *b; + + r = (float *)p->data[2]; + g = (float *)p->data[0]; + b = (float *)p->data[1]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + r[j] = av_int2float(half2float(AV_RL16(s->bytestream+0), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + g[j] = av_int2float(half2float(AV_RL16(s->bytestream+2), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + b[j] = av_int2float(half2float(AV_RL16(s->bytestream+4), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + s->bytestream += 6; + } + + r += p->linesize[2] / 4; + g += p->linesize[0] / 4; + b += p->linesize[1] / 4; + } + } else { + float *r, *g, *b; + + r = (float *)p->data[2]; + g = (float *)p->data[0]; + b = (float *)p->data[1]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + r[j] = av_int2float(half2float(AV_RB16(s->bytestream+0), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + g[j] = av_int2float(half2float(AV_RB16(s->bytestream+2), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + b[j] = av_int2float(half2float(AV_RB16(s->bytestream+4), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + s->bytestream += 6; + } + + r += p->linesize[2] / 4; + g += p->linesize[0] / 4; + b += p->linesize[1] / 4; + } + } } break; case AV_PIX_FMT_GRAYF32: + if (!s->half) { if (avctx->width * avctx->height * 4 > s->bytestream_end - s->bytestream) return AVERROR_INVALIDDATA; scale = 1.f / s->scale; @@ -322,6 +384,36 @@ static int pnm_decode_frame(AVCodecContext *avctx, AVFrame *p, g += p->linesize[0] / 4; } } + } else { + if (avctx->width * avctx->height * 2 > s->bytestream_end - s->bytestream) + return AVERROR_INVALIDDATA; + scale = 1.f / s->scale; + if (s->endian) { + float *g = (float *)p->data[0]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + g[j] = av_int2float(half2float(AV_RL16(s->bytestream), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + s->bytestream += 2; + } + g += p->linesize[0] / 4; + } + } else { + float *g = (float *)p->data[0]; + for (int i = 0; i < avctx->height; i++) { + for (int j = 0; j < avctx->width; j++) { + g[j] = av_int2float(half2float(AV_RB16(s->bytestream), + s->mantissatable, + s->exponenttable, + s->offsettable)) * scale; + s->bytestream += 2; + } + g += p->linesize[0] / 4; + } + } + } break; } *got_frame = 1; @@ -401,3 +493,25 @@ const FFCodec ff_pfm_decoder = { FF_CODEC_DECODE_CB(pnm_decode_frame), }; #endif + +#if CONFIG_PHM_DECODER +static av_cold int phm_dec_init(AVCodecContext *avctx) +{ + PNMContext *s = avctx->priv_data; + + half2float_table(s->mantissatable, s->exponenttable, s->offsettable); + + return 0; +} + +const FFCodec ff_phm_decoder = { + .p.name = "phm", + .p.long_name = NULL_IF_CONFIG_SMALL("PHM (Portable HalfFloatMap) image"), + .p.type = AVMEDIA_TYPE_VIDEO, + .p.id = AV_CODEC_ID_PHM, + .p.capabilities = AV_CODEC_CAP_DR1, + .priv_data_size = sizeof(PNMContext), + .init = phm_dec_init, + FF_CODEC_DECODE_CB(pnm_decode_frame), +}; +#endif |