Browse code

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>

Oskar Arvidsson authored on 2011/03/30 00:48:47
Showing 7 changed files
... ...
@@ -143,6 +143,10 @@ void avcodec_align_dimensions2(AVCodecContext *s, int *width, int *height, int l
143 143
     case PIX_FMT_YUVJ440P:
144 144
     case PIX_FMT_YUVJ444P:
145 145
     case PIX_FMT_YUVA420P:
146
+    case PIX_FMT_YUV420P9LE:
147
+    case PIX_FMT_YUV420P9BE:
148
+    case PIX_FMT_YUV420P10LE:
149
+    case PIX_FMT_YUV420P10BE:
146 150
         w_align= 16; //FIXME check for non mpeg style codecs and use less alignment
147 151
         h_align= 16;
148 152
         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)
... ...
@@ -740,6 +740,52 @@ const AVPixFmtDescriptor av_pix_fmt_descriptors[PIX_FMT_NB] = {
740 740
         .log2_chroma_h = 1,
741 741
         .flags = PIX_FMT_HWACCEL,
742 742
     },
743
+    [PIX_FMT_YUV420P9LE] = {
744
+        .name = "yuv420p9le",
745
+        .nb_components= 3,
746
+        .log2_chroma_w= 1,
747
+        .log2_chroma_h= 1,
748
+        .comp = {
749
+            {0,1,1,0,8},        /* Y */
750
+            {1,1,1,0,8},        /* U */
751
+            {2,1,1,0,8},        /* V */
752
+        },
753
+    },
754
+    [PIX_FMT_YUV420P9BE] = {
755
+        .name = "yuv420p9be",
756
+        .nb_components= 3,
757
+        .log2_chroma_w= 1,
758
+        .log2_chroma_h= 1,
759
+        .comp = {
760
+            {0,1,1,0,8},        /* Y */
761
+            {1,1,1,0,8},        /* U */
762
+            {2,1,1,0,8},        /* V */
763
+        },
764
+        .flags = PIX_FMT_BE,
765
+    },
766
+    [PIX_FMT_YUV420P10LE] = {
767
+        .name = "yuv420p10le",
768
+        .nb_components= 3,
769
+        .log2_chroma_w= 1,
770
+        .log2_chroma_h= 1,
771
+        .comp = {
772
+            {0,1,1,0,9},        /* Y */
773
+            {1,1,1,0,9},        /* U */
774
+            {2,1,1,0,9},        /* V */
775
+        },
776
+    },
777
+    [PIX_FMT_YUV420P10BE] = {
778
+        .name = "yuv420p10be",
779
+        .nb_components= 3,
780
+        .log2_chroma_w= 1,
781
+        .log2_chroma_h= 1,
782
+        .comp = {
783
+            {0,1,1,0,9},        /* Y */
784
+            {1,1,1,0,9},        /* U */
785
+            {2,1,1,0,9},        /* V */
786
+        },
787
+        .flags = PIX_FMT_BE,
788
+    },
743 789
     [PIX_FMT_YUV420P16LE] = {
744 790
         .name = "yuv420p16le",
745 791
         .nb_components= 3,
... ...
@@ -135,6 +135,13 @@ enum PixelFormat {
135 135
     PIX_FMT_Y400A,     ///< 8bit gray, 8bit alpha
136 136
     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
137 137
     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
138
+
139
+    //the following 4 formats are deprecated and should be replaced by PIX_FMT_YUV420P16* with the bpp stored seperately
140
+    PIX_FMT_YUV420P9LE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
141
+    PIX_FMT_YUV420P9BE, ///< planar YUV 4:2:0, 13.5bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
142
+    PIX_FMT_YUV420P10LE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), little-endian
143
+    PIX_FMT_YUV420P10BE,///< planar YUV 4:2:0, 15bpp, (1 Cr & Cb sample per 2x2 Y samples), big-endian
144
+
138 145
     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
139 146
 };
140 147
 
... ...
@@ -159,6 +166,8 @@ enum PixelFormat {
159 159
 #define PIX_FMT_BGR555 PIX_FMT_NE(BGR555BE, BGR555LE)
160 160
 #define PIX_FMT_BGR444 PIX_FMT_NE(BGR444BE, BGR444LE)
161 161
 
162
+#define PIX_FMT_YUV420P9  PIX_FMT_NE(YUV420P9BE , YUV420P9LE)
163
+#define PIX_FMT_YUV420P10 PIX_FMT_NE(YUV420P10BE, YUV420P10LE)
162 164
 #define PIX_FMT_YUV420P16 PIX_FMT_NE(YUV420P16BE, YUV420P16LE)
163 165
 #define PIX_FMT_YUV422P16 PIX_FMT_NE(YUV422P16BE, YUV422P16LE)
164 166
 #define PIX_FMT_YUV444P16 PIX_FMT_NE(YUV444P16BE, YUV444P16LE)
... ...
@@ -1747,7 +1747,28 @@ static int planarCopyWrapper(SwsContext *c, const uint8_t* src[], int srcStride[
1747 1747
                 length*=2;
1748 1748
             fillPlane(dst[plane], dstStride[plane], length, height, y, (plane==3) ? 255 : 128);
1749 1749
         } else {
1750
-            if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {
1750
+            if(isNBPS(c->srcFormat)) {
1751
+                const int depth = av_pix_fmt_descriptors[c->srcFormat].comp[plane].depth_minus1+1;
1752
+                uint16_t *srcPtr2 = (uint16_t*)srcPtr;
1753
+
1754
+                if (is16BPS(c->dstFormat)) {
1755
+                    uint16_t *dstPtr2 = (uint16_t*)dstPtr;
1756
+                    for (i = 0; i < height; i++) {
1757
+                        for (j = 0; j < length; j++)
1758
+                            dstPtr2[j] = (srcPtr2[j]<<(16-depth)) | (srcPtr2[j]>>(2*depth-16));
1759
+                        dstPtr2 += dstStride[plane]/2;
1760
+                        srcPtr2 += srcStride[plane]/2;
1761
+                    }
1762
+                } else {
1763
+                    // FIXME Maybe dither instead.
1764
+                    for (i = 0; i < height; i++) {
1765
+                        for (j = 0; j < length; j++)
1766
+                            dstPtr[j] = srcPtr2[j]>>(depth-8);
1767
+                        dstPtr  += dstStride[plane];
1768
+                        srcPtr2 += srcStride[plane]/2;
1769
+                    }
1770
+                }
1771
+            } else if(is16BPS(c->srcFormat) && !is16BPS(c->dstFormat)) {
1751 1772
                 if (!isBE(c->srcFormat)) srcPtr++;
1752 1773
                 for (i=0; i<height; i++) {
1753 1774
                     for (j=0; j<length; j++) dstPtr[j] = srcPtr[j<<1];
... ...
@@ -352,6 +352,12 @@ const char *sws_format_name(enum PixelFormat format);
352 352
         || (x)==PIX_FMT_YUV422P16BE \
353 353
         || (x)==PIX_FMT_YUV444P16BE \
354 354
     )
355
+#define isNBPS(x)       (           \
356
+           (x)==PIX_FMT_YUV420P9LE  \
357
+        || (x)==PIX_FMT_YUV420P9BE  \
358
+        || (x)==PIX_FMT_YUV420P10LE \
359
+        || (x)==PIX_FMT_YUV420P10BE \
360
+    )
355 361
 #define isBE(x) ((x)&1)
356 362
 #define isPlanar8YUV(x) (           \
357 363
            (x)==PIX_FMT_YUV410P     \
... ...
@@ -366,9 +372,13 @@ const char *sws_format_name(enum PixelFormat format);
366 366
     )
367 367
 #define isPlanarYUV(x)  (           \
368 368
         isPlanar8YUV(x)             \
369
+        || (x)==PIX_FMT_YUV420P9LE  \
370
+        || (x)==PIX_FMT_YUV420P10LE \
369 371
         || (x)==PIX_FMT_YUV420P16LE \
370 372
         || (x)==PIX_FMT_YUV422P16LE \
371 373
         || (x)==PIX_FMT_YUV444P16LE \
374
+        || (x)==PIX_FMT_YUV420P9BE  \
375
+        || (x)==PIX_FMT_YUV420P10BE \
372 376
         || (x)==PIX_FMT_YUV420P16BE \
373 377
         || (x)==PIX_FMT_YUV422P16BE \
374 378
         || (x)==PIX_FMT_YUV444P16BE \
... ...
@@ -1826,6 +1826,29 @@ static inline void RENAME(nv21ToUV)(uint8_t *dstU, uint8_t *dstV,
1826 1826
     RENAME(nvXXtoUV)(dstV, dstU, src1, width);
1827 1827
 }
1828 1828
 
1829
+// FIXME Maybe dither instead.
1830
+#define YUV_NBPS(depth) \
1831
+static inline void RENAME(yuv ## depth ## ToUV)(uint8_t *dstU, uint8_t *dstV, \
1832
+                                     const uint16_t *srcU, const uint16_t *srcV, \
1833
+                                     long width, uint32_t *unused) \
1834
+{ \
1835
+    int i; \
1836
+    for (i = 0; i < width; i++) { \
1837
+        dstU[i] = srcU[i]>>(depth-8); \
1838
+        dstV[i] = srcV[i]>>(depth-8); \
1839
+    } \
1840
+} \
1841
+\
1842
+static inline void RENAME(yuv ## depth ## ToY)(uint8_t *dstY, const uint16_t *srcY, long width, uint32_t *unused) \
1843
+{ \
1844
+    int i; \
1845
+    for (i = 0; i < width; i++) \
1846
+        dstY[i] = srcY[i]>>(depth-8); \
1847
+} \
1848
+
1849
+YUV_NBPS( 9)
1850
+YUV_NBPS(10)
1851
+
1829 1852
 #if COMPILE_TEMPLATE_MMX
1830 1853
 static inline void RENAME(bgr24ToY_mmx)(uint8_t *dst, const uint8_t *src, long width, enum PixelFormat srcFormat)
1831 1854
 {
... ...
@@ -2955,6 +2978,8 @@ static void RENAME(sws_init_swScale)(SwsContext *c)
2955 2955
         case PIX_FMT_PAL8     :
2956 2956
         case PIX_FMT_BGR4_BYTE:
2957 2957
         case PIX_FMT_RGB4_BYTE: c->chrToYV12 = palToUV; break;
2958
+        case PIX_FMT_YUV420P9 : c->chrToYV12 = (void*)RENAME(yuv9ToUV ); break;
2959
+        case PIX_FMT_YUV420P10: c->chrToYV12 = (void*)RENAME(yuv10ToUV); break;
2958 2960
         case PIX_FMT_YUV420P16BE:
2959 2961
         case PIX_FMT_YUV422P16BE:
2960 2962
         case PIX_FMT_YUV444P16BE: c->chrToYV12 = RENAME(BEToUV); break;
... ...
@@ -3001,6 +3026,8 @@ static void RENAME(sws_init_swScale)(SwsContext *c)
3001 3001
     c->lumToYV12 = NULL;
3002 3002
     c->alpToYV12 = NULL;
3003 3003
     switch (srcFormat) {
3004
+    case PIX_FMT_YUV420P9 : c->lumToYV12 = (void*)RENAME(yuv9ToY ); break;
3005
+    case PIX_FMT_YUV420P10: c->lumToYV12 = (void*)RENAME(yuv10ToY); break;
3004 3006
     case PIX_FMT_YUYV422  :
3005 3007
     case PIX_FMT_YUV420P16BE:
3006 3008
     case PIX_FMT_YUV422P16BE:
... ...
@@ -112,6 +112,8 @@ const char *swscale_license(void)
112 112
         || (x)==PIX_FMT_YUV420P16BE   \
113 113
         || (x)==PIX_FMT_YUV422P16BE   \
114 114
         || (x)==PIX_FMT_YUV444P16BE   \
115
+        || (x)==PIX_FMT_YUV420P9    \
116
+        || (x)==PIX_FMT_YUV420P10   \
115 117
     )
116 118
 
117 119
 int sws_isSupportedInput(enum PixelFormat pix_fmt)