diff options
author | Oskar Arvidsson <oskar@irock.se> | 2011-03-29 17:48:47 +0200 |
---|---|---|
committer | Michael Niedermayer <michaelni@gmx.at> | 2011-04-10 22:33:41 +0200 |
commit | d4497f6dfb8dddf25b7be441f16d387aa18a65d6 (patch) | |
tree | a688c802bf50f533e5c66798c2aecc247c0e3a20 | |
parent | af0b2d6736a99203fed3014a3e83f8226dade2af (diff) | |
download | ffmpeg-d4497f6dfb8dddf25b7be441f16d387aa18a65d6.tar.gz |
Add pixel formats for 9- and 10-bit yuv420p.
Also add support for these formats in libswscale.
Needed for high bit depth h264 decoding.
Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
-rw-r--r-- | libavcodec/utils.c | 4 | ||||
-rw-r--r-- | libavutil/pixdesc.c | 46 | ||||
-rw-r--r-- | libavutil/pixfmt.h | 9 | ||||
-rw-r--r-- | libswscale/swscale.c | 23 | ||||
-rw-r--r-- | libswscale/swscale_internal.h | 10 | ||||
-rw-r--r-- | libswscale/swscale_template.c | 27 | ||||
-rw-r--r-- | libswscale/utils.c | 2 |
7 files changed, 120 insertions, 1 deletions
diff --git a/libavcodec/utils.c b/libavcodec/utils.c index a75c9ce7ea..031c3ff11d 100644 --- a/libavcodec/utils.c +++ b/libavcodec/utils.c @@ -143,6 +143,10 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int l case PIX_FMT_YUVJ440P: case PIX_FMT_YUVJ444P: case PIX_FMT_YUVA420P: + case PIX_FMT_YUV420P9LE: + case PIX_FMT_YUV420P9BE: + case PIX_FMT_YUV420P10LE: + case PIX_FMT_YUV420P10BE: w_align= 16; //FIXME check for non mpeg style codecs and use less alignment h_align= 16; if(s->codec_id == CODEC_ID_MPEG2VIDEO || s->codec_id == CODEC_ID_MJPEG || s->codec_id == CODEC_ID_AMV || s->codec_id == CODEC_ID_THP || s->codec_id == CODEC_ID_H264) diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c index 82dda06b4b..ad2f5643a5 100644 --- a/libavutil/pixdesc.c +++ b/libavutil/pixdesc.c @@ -740,6 +740,52 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB] = { .log2_chroma_h = 1, .flags = PIX_FMT_HWACCEL, }, + [PIX_FMT_YUV420P9LE] = { + .name = "yuv420p9le", + .nb_components= 3, + .log2_chroma_w= 1, + .log2_chroma_h= 1, + .comp = { + {0,1,1,0,8}, /* Y */ + {1,1,1,0,8}, /* U */ + {2,1,1,0,8}, /* V */ + }, + }, + [PIX_FMT_YUV420P9BE] = { + .name = "yuv420p9be", + .nb_components= 3, + .log2_chroma_w= 1, + .log2_chroma_h= 1, + .comp = { + {0,1,1,0,8}, /* Y */ + {1,1,1,0,8}, /* U */ + {2,1,1,0,8}, /* V */ + }, + .flags = PIX_FMT_BE, + }, + [PIX_FMT_YUV420P10LE] = { + .name = "yuv420p10le", + .nb_components= 3, + .log2_chroma_w= 1, + .log2_chroma_h= 1, + .comp = { + {0,1,1,0,9}, /* Y */ + {1,1,1,0,9}, /* U */ + {2,1,1,0,9}, /* V */ + }, + }, + [PIX_FMT_YUV420P10BE] = { + .name = "yuv420p10be", + .nb_components= 3, + .log2_chroma_w= 1, + .log2_chroma_h= 1, + .comp = { + {0,1,1,0,9}, /* Y */ + {1,1,1,0,9}, /* U */ + {2,1,1,0,9}, /* V */ + }, + .flags = PIX_FMT_BE, + }, [PIX_FMT_YUV420P16LE] = { .name = "yuv420p16le", .nb_components= 3, diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h index 69c6274489..9bf8a0af39 100644 --- a/libavutil/pixfmt.h +++ b/libavutil/pixfmt.h @@ -135,6 +135,13 @@ enum PixelFormat { PIX_FMT_Y400A, ///< 8bit gray, 8bit alpha PIX_FMT_BGR48LE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as little-endian PIX_FMT_BGR48BE, ///< packed RGB 16:16:16, 48bpp, 16B, 16G, 16R, the 2-byte value for each R/G/B component is stored as big-endian + + //the following 4 formats are deprecated and should be replaced by PIX_FMT_YUV420P16* with the bpp stored seperately + PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian + PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian + PIX_FMT_NB, ///< number of pixel formats, DO NOT USE THIS if you want to link with shared libav* because the number of formats might differ between versions }; @@ -159,6 +166,8 @@ enum PixelFormat { #define PIX_FMT_BGR555 PIX_FMT_NE(BGR555BE, BGR555LE) #define PIX_FMT_BGR444 PIX_FMT_NE(BGR444BE, BGR444LE) +#define PIX_FMT_YUV420P9 PIX_FMT_NE(YUV420P9BE , YUV420P9LE) +#define PIX_FMT_YUV420P10 PIX_FMT_NE(YUV420P10BE, YUV420P10LE) #define PIX_FMT_YUV420P16 PIX_FMT_NE(YUV420P16BE, YUV420P16LE) #define PIX_FMT_YUV422P16 PIX_FMT_NE(YUV422P16BE, YUV422P16LE) #define PIX_FMT_YUV444P16 PIX_FMT_NE(YUV444P16BE, YUV444P16LE) diff --git a/libswscale/swscale.c b/libswscale/swscale.c index e0e48088fc..7047bb80f4 100644 --- a/libswscale/swscale.c +++ b/libswscale/swscale.c @@ -1747,7 +1747,28 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[ length*=2; fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128); } else { - if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) { + if(isNBPS(c->srcFormat)) { + const int depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1; + uint16_t *srcPtr2 = (uint16_t*)srcPtr; + + if (is16BPS(c->dstFormat)) { + uint16_t *dstPtr2 = (uint16_t*)dstPtr; + for (i = 0; i < height; i++) { + for (j = 0; j < length; j++) + dstPtr2[j] = (srcPtr2[j]<<(16-depth)) | (srcPtr2[j]>>(2*depth-16)); + dstPtr2 += dstStride[plane]/2; + srcPtr2 += srcStride[plane]/2; + } + } else { + // FIXME Maybe dither instead. + for (i = 0; i < height; i++) { + for (j = 0; j < length; j++) + dstPtr[j] = srcPtr2[j]>>(depth-8); + dstPtr += dstStride[plane]; + srcPtr2 += srcStride[plane]/2; + } + } + } else if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) { if (!isBE(c->srcFormat)) srcPtr++; for (i=0; i<height; i++) { for (j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1]; diff --git a/libswscale/swscale_internal.h b/libswscale/swscale_internal.h index 16c23d2740..6604cae67d 100644 --- a/libswscale/swscale_internal.h +++ b/libswscale/swscale_internal.h @@ -352,6 +352,12 @@ const char *sws_format_name(enum PixelFormat format); || (x)==PIX_FMT_YUV422P16BE \ || (x)==PIX_FMT_YUV444P16BE \ ) +#define isNBPS(x) ( \ + (x)==PIX_FMT_YUV420P9LE \ + || (x)==PIX_FMT_YUV420P9BE \ + || (x)==PIX_FMT_YUV420P10LE \ + || (x)==PIX_FMT_YUV420P10BE \ + ) #define isBE(x) ((x)&1) #define isPlanar8YUV(x) ( \ (x)==PIX_FMT_YUV410P \ @@ -366,9 +372,13 @@ const char *sws_format_name(enum PixelFormat format); ) #define isPlanarYUV(x) ( \ isPlanar8YUV(x) \ + || (x)==PIX_FMT_YUV420P9LE \ + || (x)==PIX_FMT_YUV420P10LE \ || (x)==PIX_FMT_YUV420P16LE \ || (x)==PIX_FMT_YUV422P16LE \ || (x)==PIX_FMT_YUV444P16LE \ + || (x)==PIX_FMT_YUV420P9BE \ + || (x)==PIX_FMT_YUV420P10BE \ || (x)==PIX_FMT_YUV420P16BE \ || (x)==PIX_FMT_YUV422P16BE \ || (x)==PIX_FMT_YUV444P16BE \ diff --git a/libswscale/swscale_template.c b/libswscale/swscale_template.c index 0ee5181e2e..d616036646 100644 --- a/libswscale/swscale_template.c +++ b/libswscale/swscale_template.c @@ -1826,6 +1826,29 @@ static inline void RENAME(nv21ToUV)(uint8_t *dstU, uint8_t *dstV, RENAME(nvXXtoUV)(dstV, dstU, src1, width); } +// FIXME Maybe dither instead. +#define YUV_NBPS(depth) \ +static inline void RENAME(yuv ## depth ## ToUV)(uint8_t *dstU, uint8_t *dstV, \ + const uint16_t *srcU, const uint16_t *srcV, \ + long width, uint32_t *unused) \ +{ \ + int i; \ + for (i = 0; i < width; i++) { \ + dstU[i] = srcU[i]>>(depth-8); \ + dstV[i] = srcV[i]>>(depth-8); \ + } \ +} \ +\ +static inline void RENAME(yuv ## depth ## ToY)(uint8_t *dstY, const uint16_t *srcY, long width, uint32_t *unused) \ +{ \ + int i; \ + for (i = 0; i < width; i++) \ + dstY[i] = srcY[i]>>(depth-8); \ +} \ + +YUV_NBPS( 9) +YUV_NBPS(10) + #if COMPILE_TEMPLATE_MMX static inline void RENAME(bgr24ToY_mmx)(uint8_t *dst, const uint8_t *src, long width, enum PixelFormat srcFormat) { @@ -2955,6 +2978,8 @@ static void RENAME(sws_init_swScale)(SwsContext *c) case PIX_FMT_PAL8 : case PIX_FMT_BGR4_BYTE: case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV; break; + case PIX_FMT_YUV420P9 : c->chrToYV12 = (void*)RENAME(yuv9ToUV ); break; + case PIX_FMT_YUV420P10: c->chrToYV12 = (void*)RENAME(yuv10ToUV); break; case PIX_FMT_YUV420P16BE: case PIX_FMT_YUV422P16BE: case PIX_FMT_YUV444P16BE: c->chrToYV12 = RENAME(BEToUV); break; @@ -3001,6 +3026,8 @@ static void RENAME(sws_init_swScale)(SwsContext *c) c->lumToYV12 = NULL; c->alpToYV12 = NULL; switch (srcFormat) { + case PIX_FMT_YUV420P9 : c->lumToYV12 = (void*)RENAME(yuv9ToY ); break; + case PIX_FMT_YUV420P10: c->lumToYV12 = (void*)RENAME(yuv10ToY); break; case PIX_FMT_YUYV422 : case PIX_FMT_YUV420P16BE: case PIX_FMT_YUV422P16BE: diff --git a/libswscale/utils.c b/libswscale/utils.c index 9accfdadd0..a343bf2570 100644 --- a/libswscale/utils.c +++ b/libswscale/utils.c @@ -112,6 +112,8 @@ const char *swscale_license(void) || (x)==PIX_FMT_YUV420P16BE \ || (x)==PIX_FMT_YUV422P16BE \ || (x)==PIX_FMT_YUV444P16BE \ + || (x)==PIX_FMT_YUV420P9 \ + || (x)==PIX_FMT_YUV420P10 \ ) int sws_isSupportedInput(enum PixelFormat pix_fmt) |