Kostya Shishkov <[email protected]> wrote:

>---
>Why: I need to dump 8- and 10-bit data into frames at work, so I've
>picked the
>simplest format standard tools (e.g. ImageMagic) can handle.
>But since Libav couldn't handle it I tried to add higher bitdepth
>support for
>its PGMYUV decoder, and tried to do it properly, and tried to add
>encoder
>counterpart too. Hence this patch.
>
>P.S. FATE test would be nice too.
>---
> libavcodec/pnm.c    |    9 ++++++++-
>libavcodec/pnmdec.c |   45
>+++++++++++++++++++++++++++++++++++++++++++++
> libavcodec/pnmenc.c |   15 ++++++++++++---
> 3 files changed, 65 insertions(+), 4 deletions(-)
>
>diff --git a/libavcodec/pnm.c b/libavcodec/pnm.c
>index 5d13650..094e03d 100644
>--- a/libavcodec/pnm.c
>+++ b/libavcodec/pnm.c
>@@ -157,6 +157,13 @@ int ff_pnm_decode_header(AVCodecContext *avctx,
>PNMContext * const s)
>             } else if (avctx->pix_fmt == AV_PIX_FMT_RGB24) {
>                 if (s->maxval > 255)
>                     avctx->pix_fmt = AV_PIX_FMT_RGB48BE;
>+            } else if (avctx->pix_fmt == AV_PIX_FMT_YUV420P &&
>s->maxval < 65536) {
>+                if (s->maxval < 512)
>+                    avctx->pix_fmt = AV_PIX_FMT_YUV420P9BE;
>+                else if (s->maxval < 1024)
>+                    avctx->pix_fmt = AV_PIX_FMT_YUV420P10BE;
>+                else
>+                    avctx->pix_fmt = AV_PIX_FMT_YUV420P16;
>             } else {
>             av_log(avctx, AV_LOG_ERROR, "Unsupported pixel format\n");
>                 avctx->pix_fmt = AV_PIX_FMT_NONE;
>@@ -166,7 +173,7 @@ int ff_pnm_decode_header(AVCodecContext *avctx,
>PNMContext * const s)
>     }else
>         s->maxval=1;
>     /* more check if YUV420 */
>-    if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
>+    if (av_pix_fmt_descriptors[avctx->pix_fmt].flags & PIX_FMT_PLANAR)
>{
>         if ((avctx->width & 1) != 0)
>             return AVERROR_INVALIDDATA;
>         h = (avctx->height * 2);
>diff --git a/libavcodec/pnmdec.c b/libavcodec/pnmdec.c
>index b9897b9..c9b873d 100644
>--- a/libavcodec/pnmdec.c
>+++ b/libavcodec/pnmdec.c
>@@ -135,12 +135,16 @@ static int pnm_decode_frame(AVCodecContext
>*avctx, void *data,
>         }
>         break;
>     case AV_PIX_FMT_YUV420P:
>+    case AV_PIX_FMT_YUV420P9BE:
>+    case AV_PIX_FMT_YUV420P10BE:
>         {
>             unsigned char *ptr1, *ptr2;
> 
>             n        = avctx->width;
>             ptr      = p->data[0];
>             linesize = p->linesize[0];
>+            if (s->maxval >= 256)
>+                n *= 2;
>     if (s->bytestream + n * avctx->height * 3 / 2 > s->bytestream_end)
>                 return AVERROR_INVALIDDATA;
>             for (i = 0; i < avctx->height; i++) {
>@@ -162,6 +166,47 @@ static int pnm_decode_frame(AVCodecContext *avctx,
>void *data,
>             }
>         }
>         break;
>+    case AV_PIX_FMT_YUV420P16:
>+        {
>+            uint16_t *ptr1, *ptr2;
>+            const int f = (65535 * 32768 + s->maxval / 2) / s->maxval;
>+            unsigned int j, v;
>+
>+            n        = avctx->width * 2;
>+            ptr      = p->data[0];
>+            linesize = p->linesize[0];
>+            if (s->bytestream + n * avctx->height * 3 / 2 >
>s->bytestream_end)
>+                return AVERROR_INVALIDDATA;
>+            for (i = 0; i < avctx->height; i++) {
>+                for (j = 0; j < n / 2; j++) {
>+                    v = av_be2ne16(((uint16_t *)s->bytestream)[j]);
>+                    ((uint16_t *)ptr)[j] = (v * f + 16384) >> 15;
>+                }
>+                s->bytestream += n;
>+                ptr           += linesize;
>+            }
>+            ptr1 = (uint16_t*)p->data[1];
>+            ptr2 = (uint16_t*)p->data[2];
>+            n >>= 1;
>+            h = avctx->height >> 1;
>+            for (i = 0; i < h; i++) {
>+                for (j = 0; j < n / 2; j++) {
>+                    v = av_be2ne16(((uint16_t *)s->bytestream)[j]);
>+                    ptr1[j] = (v * f + 16384) >> 15;
>+                }
>+                s->bytestream += n;
>+
>+                for (j = 0; j < n / 2; j++) {
>+                    v = av_be2ne16(((uint16_t *)s->bytestream)[j]);
>+                    ptr2[j] = (v * f + 16384) >> 15;
>+                }
>+                s->bytestream += n;
>+
>+                ptr1 += p->linesize[1] / 2;
>+                ptr2 += p->linesize[2] / 2;
>+            }
>+        }
>+        break;
>     case AV_PIX_FMT_RGB32:
>         ptr      = p->data[0];
>         linesize = p->linesize[0];
>diff --git a/libavcodec/pnmenc.c b/libavcodec/pnmenc.c
>index 2863db7..b096492 100644
>--- a/libavcodec/pnmenc.c
>+++ b/libavcodec/pnmenc.c
>@@ -19,6 +19,7 @@
>* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
>02110-1301 USA
>  */
> 
>+#include "libavutil/pixdesc.h"
> #include "avcodec.h"
> #include "bytestream.h"
> #include "internal.h"
>@@ -76,6 +77,11 @@ static int pnm_encode_frame(AVCodecContext *avctx,
>AVPacket *pkt,
>         n  = avctx->width;
>         h1 = (h * 3) / 2;
>         break;
>+    case AV_PIX_FMT_YUV420P16BE:
>+        c  = '5';
>+        n  = avctx->width * 2;
>+        h1 = (h * 3) / 2;
>+        break;
>     default:
>         return -1;
>     }
>@@ -83,8 +89,9 @@ static int pnm_encode_frame(AVCodecContext *avctx,
>AVPacket *pkt,
>              "P%c\n%d %d\n", c, avctx->width, h1);
>     s->bytestream += strlen(s->bytestream);
>     if (avctx->pix_fmt != AV_PIX_FMT_MONOWHITE) {
>+        int maxdepth = (1 <<
>(av_pix_fmt_descriptors[avctx->pix_fmt].comp[0].depth_minus1 + 1)) - 1;
>         snprintf(s->bytestream, s->bytestream_end - s->bytestream,
>-                 "%d\n", (avctx->pix_fmt != AV_PIX_FMT_GRAY16BE &&
>avctx->pix_fmt != AV_PIX_FMT_RGB48BE) ? 255 : 65535);
>+                 "%d\n", maxdepth);
>         s->bytestream += strlen(s->bytestream);
>     }
> 
>@@ -96,7 +103,7 @@ static int pnm_encode_frame(AVCodecContext *avctx,
>AVPacket *pkt,
>         ptr           += linesize;
>     }
> 
>-    if (avctx->pix_fmt == AV_PIX_FMT_YUV420P) {
>+    if (avctx->pix_fmt == AV_PIX_FMT_YUV420P || avctx->pix_fmt ==
>AV_PIX_FMT_YUV420P16BE) {
>         h >>= 1;
>         n >>= 1;
>         ptr1 = p->data[1];
>@@ -141,7 +148,9 @@ AVCodec ff_pgmyuv_encoder = {
>     .priv_data_size = sizeof(PNMContext),
>     .init           = ff_pnm_init,
>     .encode2        = pnm_encode_frame,
>-    .pix_fmts       = (const enum AVPixelFormat[]){
>AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
>+    .pix_fmts       = (const enum AVPixelFormat[]){
>+        AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE
>+    },
>.long_name      = NULL_IF_CONFIG_SMALL("PGMYUV (Portable GrayMap YUV)
>image"),
> };
> #endif

Seems interesting.
_______________________________________________
libav-devel mailing list
[email protected]
https://lists.libav.org/mailman/listinfo/libav-devel

Reply via email to