home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Meia / source / decode_huffyuv.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2010-04-13  |  31.8 KB  |  1,198 lines

  1. //    VirtualDub - Video processing and capture application
  2. //    Video decoding library
  3. //    Copyright (C) 1998-2008 Avery Lee
  4. //
  5. //    This program is free software; you can redistribute it and/or modify
  6. //    it under the terms of the GNU General Public License as published by
  7. //    the Free Software Foundation; either version 2 of the License, or
  8. //    (at your option) any later version.
  9. //
  10. //    This program is distributed in the hope that it will be useful,
  11. //    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. //    GNU General Public License for more details.
  14. //
  15. //    You should have received a copy of the GNU General Public License
  16. //    along with this program; if not, write to the Free Software
  17. //    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18.  
  19. #include <vd2/system/binary.h>
  20. #include <vd2/system/bitmath.h>
  21. #include <vd2/system/cpuaccel.h>
  22. #include <vd2/system/debug.h>
  23. #include <vd2/system/error.h>
  24. #include <vd2/system/memory.h>
  25. #include <vd2/system/vdstl.h>
  26. #include <vd2/Meia/decode_huffyuv.h>
  27. #include <vd2/Kasumi/pixmap.h>
  28. #include <vd2/Kasumi/pixmaputils.h>
  29.  
  30. #include <map>
  31. #include <deque>
  32.  
  33. #include <intrin.h>
  34.  
  35. #pragma intrinsic(__ll_lshift)
  36.  
  37. //#define SEARCH_BASED_DECODE
  38.  
  39. namespace {
  40.     struct HuffmanDecodeTable {
  41.         uint32 mBaseLen;
  42.  
  43. #ifdef SEARCH_BASED_DECODE
  44.         const uint8 (*mCodeBase[32])[2];
  45.         uint32 mCodeStart[32];
  46.         uint32 mCodeLimit[32];
  47.         uint8 mCodeTable[256][2];
  48. #endif
  49.  
  50.         uintptr mBsrLenTable[32];
  51.         uint8 mBsrShiftTable[32];
  52.  
  53.         // TODO: Find true limit.
  54.         //
  55.         // The justification for this limit is as follows: the maximum space waste occurs when
  56.         // the difference in code lengths is the largest within the same leading bit position.
  57.         // The worst case situation happens like this:
  58.         //
  59.         //    11
  60.         //    101
  61.         //    1001
  62.         //    10001
  63.         //    100001
  64.         //    1000001
  65.         //    ...
  66.         //
  67.         // However, because Huffyuv requires codes to be allocated in order of descending code
  68.         // length and because there are only 256 codes to allocate, there is a limit to how far
  69.         // this can go, because eventually the 0xxxxxxx codes must be counted away, and they
  70.         // must be counted away with encodings as least as long as the last code. This limits
  71.         // the longest practical code above to about 100000001.
  72.         //
  73.         // I believe the lowest efficiency possible for this table is just over 50%, so somewhere
  74.         // between 512 and 1024 entries would be the max. Since I don't have a proof, it's 1024
  75.         // and the decoder routine checks for overflow instead.
  76.         //
  77.         uint8 mBsrCodeTable[1024*2];
  78.  
  79.         const uint8 *Init(const uint8 *src, uint32 len);
  80.     };
  81.  
  82.     const uint8 *HuffmanDecodeTable::Init(const uint8 *src, uint32 len) {
  83.         const uint8 *limit = src + len;
  84.         uint8 tab[256];
  85.  
  86.         // decompress table of bit lengths per code
  87.         int i=0;
  88.         while(i < 256) {
  89.             if (src >= limit)
  90.                 throw MyError("Decompression error: Invalid VLC table detected in Huffyuv format.");
  91.  
  92.             uint8 code = *src++;
  93.             uint8 v = code & 31;
  94.             uint8 count = code >> 5;
  95.  
  96.             if (!count) {
  97.                 if (src >= limit)
  98.                     throw MyError("Decompression error: Invalid VLC table detected in Huffyuv format.");
  99.  
  100.                 count = *src++;
  101.                 if (!count)
  102.                     throw MyError("Decompression error: Invalid VLC table detected in Huffyuv format.");
  103.             }
  104.  
  105.             if (count + i > 256)
  106.                 throw MyError("Decompression error: Invalid VLC table detected in Huffyuv format.");
  107.  
  108.             while(count--)
  109.                 tab[i++] = v;
  110.         }
  111.  
  112.         uint32 total = 0;
  113.         uint32 base = 0;
  114.         uint8 *decdst = mBsrCodeTable;
  115.         uint8 *declimit = mBsrCodeTable + sizeof mBsrCodeTable;
  116.  
  117.         int curdecidx = -1;
  118.  
  119.         for(int i=0; i<32; ++i)
  120.             mBsrShiftTable[i] = 32;
  121.  
  122.         // assign bit patterns starting at 0 to codes by decreasing bit length
  123.         i = 0;
  124.         for(uint32 len=32; len >= 1; --len) {
  125.             if (!i)
  126.                 mBaseLen = len;
  127.  
  128. #ifdef SEARCH_BASED_DECODE
  129.             mCodeBase[len - 1] = mCodeTable + i;
  130.             mCodeStart[len - 1] = base;
  131. #endif
  132.  
  133.             uint32 inc = 0x80000000 >> (len - 1);
  134.  
  135.             uint32 prevBase = base;
  136.  
  137.             for(int j=0; j<256; ++j) {
  138.                 if (tab[j] == len) {
  139.                     if (i >= 256)
  140.                         throw MyError("Decompression error: Invalid VLC table detected in Huffyuv format.");
  141.  
  142. #ifdef SEARCH_BASED_DECODE
  143.                     mCodeTable[i][0] = j;
  144.                     mCodeTable[i][1] = len;
  145. #endif
  146.                     ++i;
  147.  
  148.                     int firstidx = VDFindHighestSetBit(base | 1);
  149.                     base += inc;
  150.  
  151.                     int decidx = VDFindHighestSetBit((base - 1) | 1);
  152.  
  153.                     int basedecidx = curdecidx;
  154.                     while(curdecidx < decidx) {
  155.                         if (curdecidx >= 0) {
  156.                             int decrepeat = 1 << (32 - mBsrShiftTable[curdecidx] - len);
  157.                             if (declimit - decdst < 2*decrepeat)
  158.                                 throw MyError("Internal error: Insufficient space for Huffman decoding table.");
  159.  
  160.                             while(decrepeat--) {
  161.                                 *decdst++ = (uint8)j;
  162.                                 *decdst++ = (uint8)len;
  163.                             }
  164.                         }
  165.  
  166.                         ++curdecidx;
  167.                         unsigned shift = mBsrShiftTable[curdecidx];
  168.                         if (shift > 32-len) {
  169.                             shift = 32-len;
  170.                             mBsrShiftTable[curdecidx] = 32-len;
  171.                             mBsrLenTable[curdecidx] = (uintptr)decdst - 2*((1U << curdecidx) >> shift);
  172.                         }
  173.                     }
  174.  
  175.                     int decrepeat = 1 << (32 - mBsrShiftTable[curdecidx] - len);
  176.                     if (declimit - decdst < 2*decrepeat)
  177.                         throw MyError("Internal error: Insufficient space for Huffman decoding table.");
  178.  
  179.                     while(decrepeat--) {
  180.                         *decdst++ = (uint8)j;
  181.                         *decdst++ = (uint8)len;
  182.                     }
  183.  
  184. #if 0
  185.                     for(uint32 k=base-inc; k != base; ++k) {
  186.                         int idx = VDFindHighestSetBit(k | 1);
  187.  
  188.                         uint8 code = *(const char *)(mBsrLenTable[idx] + 2*(k >> mBsrShiftTable[idx]));
  189.                         VDASSERT(code == j);
  190.                     }
  191. #endif
  192.  
  193.                     if (base && base < prevBase)
  194.                         throw MyError("Decompression error: Invalid VLC table detected in Huffyuv format.");
  195.                 }
  196.             }
  197.  
  198. #ifdef SEARCH_BASED_DECODE
  199.             mCodeLimit[len - 1] = base - 1;
  200. #endif
  201.         }
  202.  
  203.         if (base)
  204.             throw MyError("Decompression error: Invalid VLC table detected in Huffyuv format.");
  205.  
  206.         return src;
  207.     }
  208.  
  209. //#define SHLD(dst, src, count) (uint32)(__ll_lshift(((uint64)(uint32)(dst) << 32) | (uint32)(src), (count) & 31) >> 32)
  210. #define SHLD(dst, src, count) (uint32)(((((uint64)(uint32)(dst) << 32) | (uint32)(src)) << ((count) & 31)) >> 32)
  211.  
  212. #define CONSUME(bits) (pos += (bits))
  213.  
  214. #ifdef SEARCH_BASED_DECODE
  215.     #define DECODE(result, table)    \
  216.         {    \
  217.             const uint32 posidx = (pos >> 5);    \
  218.             const uint32 bitpos = pos & 31;    \
  219.             uint32 code = (src32[posidx] << bitpos) + ((src32[posidx + 1] >> (31-bitpos)) >> 1); \
  220.             for(int bitlen = table->mBaseLen; bitlen >= 1; --bitlen) {    \
  221.                 if (code <= table->mCodeLimit[bitlen - 1]) {    \
  222.                     result = table->mCodeBase[bitlen - 1][(code - table->mCodeStart[bitlen - 1]) >> (32 - bitlen)][0];    \
  223.                     CONSUME(bitlen);    \
  224.                     break;    \
  225.                 }    \
  226.             }    \
  227.         }
  228. #else
  229. #ifdef _M_IX86
  230.     #define LSHIFT(x, y) __ll_lshift((x), (y))
  231. #else
  232.     #define LSHIFT(x, y) __ll_lshift((x), (y) & 31)
  233. #endif
  234.  
  235. #define DECODE(result, table)    \
  236.     {    \
  237.         const uint32 posidx = (pos >> 5);    \
  238.         union {    \
  239.             struct {    \
  240.                 uint32 a, b;    \
  241.             } d;    \
  242.             uint64 q;    \
  243.         } conv = { { src32[posidx+1], src32[posidx] } };    \
  244.         conv.q = LSHIFT(conv.q, pos);    \
  245.         uint32 code = conv.d.b | 1;    \
  246.         uint32 idx = VDFindHighestSetBitFast(code);    \
  247.         const uint8 *p = (const uint8 *)(table->mBsrLenTable[idx] + 2*(code >> table->mBsrShiftTable[idx]));    \
  248.         result = p[0];    \
  249.         CONSUME(p[1]);    \
  250.     }
  251. #endif
  252.  
  253. #define DECLARE_TABLES_Y()    \
  254.         const HuffmanDecodeTable * VDRESTRICT tabY = &tables[0]
  255.  
  256. #define DECLARE_TABLES_YUV()    \
  257.         const HuffmanDecodeTable * VDRESTRICT tabY = &tables[0];    \
  258.         const HuffmanDecodeTable * VDRESTRICT tabU = &tables[1];    \
  259.         const HuffmanDecodeTable * VDRESTRICT tabV = &tables[2]
  260.  
  261. #define DECLARE_PREDICTORS_Y()    \
  262.         uint8 predY = predictors[0]
  263.  
  264. #define DECLARE_PREDICTORS_YUV()    \
  265.         uint8 predY = predictors[0];    \
  266.         uint8 predU = predictors[1];    \
  267.         uint8 predV = predictors[2]
  268.  
  269. #define WRITE_PREDICTORS_Y()    \
  270.         predictors[0] = predY
  271.  
  272. #define WRITE_PREDICTORS_YUV()    \
  273.         predictors[0] = predY;    \
  274.         predictors[1] = predU;    \
  275.         predictors[2] = predV
  276.  
  277.     uint32 DecodeYUY2(uint8 *VDRESTRICT dst, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables) {
  278.         DECLARE_TABLES_YUV();
  279.         uint8 y1;
  280.         uint8 u;
  281.         uint8 y2;
  282.         uint8 v;
  283.  
  284.         do {
  285.             DECODE(y1, tabY);
  286.             DECODE(u, tabU);
  287.             DECODE(y2, tabY);
  288.             DECODE(v, tabV);
  289.  
  290.             *dst++ = y1;
  291.             *dst++ = u;
  292.             *dst++ = y2;
  293.             *dst++ = v;
  294.         } while(--count);
  295.  
  296.         return pos;
  297.     }
  298.  
  299.     uint32 DecodeYUY2PredictLeft(uint8 *VDRESTRICT dst, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables, uint8 *VDRESTRICT predictors) {
  300.         DECLARE_TABLES_YUV();
  301.         DECLARE_PREDICTORS_YUV();
  302.         uint8 y1;
  303.         uint8 u;
  304.         uint8 y2;
  305.         uint8 v;
  306.  
  307.         do {
  308.             DECODE(y1, tabY);
  309.             DECODE(u, tabU);
  310.             DECODE(y2, tabY);
  311.             DECODE(v, tabV);
  312.  
  313.             predY += y1;
  314.             *dst++ = predY;
  315.  
  316.             predU += u;
  317.             *dst++ = predU;
  318.  
  319.             predY += y2;
  320.             *dst++ = predY;
  321.  
  322.             predV += v;
  323.             *dst++ = predV;
  324.         } while(--count);
  325.  
  326.         WRITE_PREDICTORS_YUV();
  327.  
  328.         return pos;
  329.     }
  330.  
  331.     uint32 DecodeY8(uint8 *VDRESTRICT dst, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables) {
  332.         DECLARE_TABLES_Y();
  333.         uint8 y1;
  334.         uint8 y2;
  335.  
  336.         do {
  337.             DECODE(y1, tabY);
  338.             DECODE(y2, tabY);
  339.  
  340.             *dst++ = y1;
  341.             *dst++ = y2;
  342.         } while(--count);
  343.  
  344.         return pos;
  345.     }
  346.  
  347.     uint32 DecodeY8PredictLeft(uint8 *VDRESTRICT dst, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables, uint8 *VDRESTRICT predictors) {
  348.         DECLARE_TABLES_Y();
  349.         DECLARE_PREDICTORS_Y();
  350.         uint8 y1;
  351.         uint8 y2;
  352.  
  353.         do {
  354.             DECODE(y1, tabY);
  355.             DECODE(y2, tabY);
  356.  
  357.             predY += y1;
  358.             *dst++ = predY;
  359.  
  360.             predY += y2;
  361.             *dst++ = predY;
  362.         } while(--count);
  363.  
  364.         WRITE_PREDICTORS_Y();
  365.  
  366.         return pos;
  367.     }
  368.  
  369.     uint32 DecodeYV12(uint8 *VDRESTRICT dstY, uint8 *VDRESTRICT dstU, uint8 *VDRESTRICT dstV, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables) {
  370.         DECLARE_TABLES_YUV();
  371.         uint8 y1;
  372.         uint8 u;
  373.         uint8 y2;
  374.         uint8 v;
  375.  
  376.         do {
  377.             DECODE(y1, tabY);
  378.             DECODE(u, tabU);
  379.             DECODE(y2, tabY);
  380.             DECODE(v, tabV);
  381.  
  382.             *dstY++ = y1;
  383.             *dstU++ = u;
  384.             *dstY++ = y2;
  385.             *dstV++ = v;
  386.         } while(--count);
  387.  
  388.         return pos;
  389.     }
  390.  
  391.     uint32 DecodeYV12PredictLeft(uint8 *VDRESTRICT dstY, uint8 *VDRESTRICT dstU, uint8 *VDRESTRICT dstV, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables, uint8 *VDRESTRICT predictors) {
  392.         DECLARE_TABLES_YUV();
  393.         DECLARE_PREDICTORS_YUV();
  394.         uint8 y1;
  395.         uint8 u;
  396.         uint8 y2;
  397.         uint8 v;
  398.  
  399.         do {
  400.             DECODE(y1, tabY);
  401.             DECODE(u, tabU);
  402.             DECODE(y2, tabY);
  403.             DECODE(v, tabV);
  404.  
  405.             predY += y1;
  406.             *dstY++ = predY;
  407.  
  408.             predU += u;
  409.             *dstU++ = predU;
  410.  
  411.             predY += y2;
  412.             *dstY++ = predY;
  413.  
  414.             predV += v;
  415.             *dstV++ = predV;
  416.         } while(--count);
  417.  
  418.         WRITE_PREDICTORS_YUV();
  419.  
  420.         return pos;
  421.     }
  422.  
  423. #define DECLARE_TABLES_RGB()    \
  424.         const HuffmanDecodeTable * VDRESTRICT tabB = &tables[0];    \
  425.         const HuffmanDecodeTable * VDRESTRICT tabG = &tables[1];    \
  426.         const HuffmanDecodeTable * VDRESTRICT tabR = &tables[2]
  427.  
  428. #define DECLARE_PREDICTORS_RGB()    \
  429.         uint8 predB = predictors[0];    \
  430.         uint8 predG = predictors[1];    \
  431.         uint8 predR = predictors[2]
  432.  
  433. #define WRITE_PREDICTORS_RGB()    \
  434.         predictors[0] = predB;    \
  435.         predictors[1] = predG;    \
  436.         predictors[2] = predR
  437.  
  438.     uint32 DecodeRGBPredictLeft(uint8 *VDRESTRICT dst, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables, uint8 *VDRESTRICT predictors) {
  439.         DECLARE_TABLES_RGB();
  440.         DECLARE_PREDICTORS_RGB();
  441.         uint8 r;
  442.         uint8 g;
  443.         uint8 b;
  444.  
  445.         do {
  446.             DECODE(b, tabB);
  447.             DECODE(g, tabG);
  448.             DECODE(r, tabR);
  449.  
  450.             predB += b;
  451.             *dst++ = predB;
  452.  
  453.             predG += g;
  454.             *dst++ = predG;
  455.  
  456.             predR += r;
  457.             *dst++ = predR;
  458.         } while(--count);
  459.  
  460.         WRITE_PREDICTORS_RGB();
  461.  
  462.         return pos;
  463.     }
  464.  
  465.     uint32 DecodeRGBPredictLeftDecorr(uint8 *VDRESTRICT dst, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables, uint8 *VDRESTRICT predictors) {
  466.         DECLARE_TABLES_RGB();
  467.         DECLARE_PREDICTORS_RGB();
  468.         uint8 r;
  469.         uint8 g;
  470.         uint8 b;
  471.  
  472.         do {
  473.             DECODE(g, tabG);
  474.             DECODE(b, tabB);
  475.             DECODE(r, tabR);
  476.  
  477.             predB += b;
  478.             predG += g;
  479.             predR += r;
  480.  
  481.             *dst++ = predB + predG;
  482.             *dst++ = predG;
  483.             *dst++ = predR + predG;
  484.  
  485.         } while(--count);
  486.  
  487.         WRITE_PREDICTORS_RGB();
  488.  
  489.         return pos;
  490.     }
  491.  
  492. #define DECLARE_PREDICTORS_RGBA()    \
  493.         uint8 predB = predictors[0];    \
  494.         uint8 predG = predictors[1];    \
  495.         uint8 predR = predictors[2];    \
  496.         uint8 predA = predictors[3]
  497.  
  498. #define WRITE_PREDICTORS_RGBA()    \
  499.         predictors[0] = predB;    \
  500.         predictors[1] = predG;    \
  501.         predictors[2] = predR;    \
  502.         predictors[3] = predA
  503.  
  504.     uint32 DecodeRGBAPredictLeft(uint8 *VDRESTRICT dst, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables, uint8 *VDRESTRICT predictors) {
  505.         DECLARE_TABLES_RGB();
  506.         DECLARE_PREDICTORS_RGBA();
  507.         uint8 r;
  508.         uint8 g;
  509.         uint8 b;
  510.         uint8 a;
  511.  
  512.         do {
  513.             DECODE(b, tabB);
  514.             DECODE(g, tabG);
  515.             DECODE(r, tabR);
  516.             DECODE(a, tabR);
  517.  
  518.             predB += b;
  519.             *dst++ = predB;
  520.  
  521.             predG += g;
  522.             *dst++ = predG;
  523.  
  524.             predR += r;
  525.             *dst++ = predR;
  526.  
  527.             predA += a;
  528.             *dst++ = predA;
  529.         } while(--count);
  530.  
  531.         WRITE_PREDICTORS_RGBA();
  532.  
  533.         return pos;
  534.     }
  535.  
  536.     uint32 DecodeRGBAPredictLeftDecorr(uint8 *VDRESTRICT dst, const uint32 *VDRESTRICT src32, uint32 pos, uint32 count, const HuffmanDecodeTable *VDRESTRICT tables, uint8 *VDRESTRICT predictors) {
  537.         DECLARE_TABLES_RGB();
  538.         DECLARE_PREDICTORS_RGBA();
  539.         uint8 r;
  540.         uint8 g;
  541.         uint8 b;
  542.         uint8 a;
  543.  
  544.         do {
  545.             DECODE(g, tabG);
  546.             DECODE(b, tabB);
  547.             DECODE(r, tabR);
  548.             DECODE(a, tabR);
  549.  
  550.             predB += b;
  551.             predG += g;
  552.             predR += r;
  553.             predA += a;
  554.  
  555.             *dst++ = predB + predG;
  556.             *dst++ = predG;
  557.             *dst++ = predR + predG;
  558.             *dst++ = predA + predG;
  559.  
  560.         } while(--count);
  561.  
  562.         WRITE_PREDICTORS_RGBA();
  563.  
  564.         return pos;
  565.     }
  566.  
  567. #undef DECODE
  568. #undef CONSUME
  569. #undef PEEK
  570. #undef SHLD
  571.  
  572.     void DecodeVerticalPrediction(uint8 *dst, const uint8 *src, uint32 count) {
  573.         do {
  574.             *dst++ += *src++;
  575.         } while(--count);
  576.     }
  577.  
  578.     void DecodeMedianPredictionYUY2(
  579.             uint8 * VDRESTRICT dst,
  580.             const uint8 * VDRESTRICT srcL,
  581.             const uint8 * VDRESTRICT srcTC,
  582.             const uint8 * VDRESTRICT srcTL,
  583.             uint32 count) {
  584. #define MEDIAN(r, a, b, c)    \
  585.                 if (a > b) { t=a; a=b; b=t; }    \
  586.                 if (b > c) { t=b; b=c; c=t; }    \
  587.                 if (a > b) { t=a; a=b; b=t; }    \
  588.                 r = b
  589.         uint8 t;
  590.         uint8 a;
  591.         uint8 b;
  592.         uint8 c;
  593.         uint8 y1;
  594.         uint8 u;
  595.         uint8 y2;
  596.         uint8 v;
  597.  
  598.         do {
  599.             a = srcTC[0];
  600.             b = srcL[2];
  601.             c = a + b - srcTL[2];
  602.  
  603.             MEDIAN(y1, a, b, c);
  604.  
  605.             a = srcTC[1];
  606.             b = srcL[1];
  607.             c = a + b - srcTL[1];
  608.  
  609.             MEDIAN(u, a, b, c);
  610.  
  611.             dst[0] += y1;
  612.             dst[1] += u;
  613.  
  614.             a = srcTC[2];
  615.             b = dst[0];
  616.             c = a + b - srcTC[0];
  617.  
  618.             MEDIAN(y2, a, b, c);
  619.  
  620.             a = srcTC[3];
  621.             b = srcL[3];
  622.             c = a + b - srcTL[3];
  623.  
  624.             MEDIAN(v, a, b, c);
  625.  
  626.             dst[2] += y2;
  627.             dst[3] += v;
  628.             dst += 4;
  629.             srcTC += 4;
  630.             srcTL += 4;
  631.             srcL += 4;
  632.         } while(--count);
  633.     }
  634.  
  635.     void DecodeMedianPredictionY8(
  636.             uint8 * VDRESTRICT dst,
  637.             const uint8 * VDRESTRICT srcL,
  638.             const uint8 * VDRESTRICT srcTC,
  639.             const uint8 * VDRESTRICT srcTL,
  640.             uint32 count) {
  641. #define MEDIAN(r, a, b, c)    \
  642.                 if (a > b) { t=a; a=b; b=t; }    \
  643.                 if (b > c) { t=b; b=c; c=t; }    \
  644.                 if (a > b) { t=a; a=b; b=t; }    \
  645.                 r = b
  646.         uint8 t;
  647.         uint8 a;
  648.         uint8 b;
  649.         uint8 c;
  650.         uint8 y;
  651.  
  652.         do {
  653.             a = srcTC[0];
  654.             b = srcL[0];
  655.             c = a + b - srcTL[0];
  656.  
  657.             MEDIAN(y, a, b, c);
  658.  
  659.             *dst++ += y;
  660.  
  661.             ++srcTC;
  662.             ++srcTL;
  663.             ++srcL;
  664.         } while(--count);
  665.     }
  666. }
  667.  
  668. class VDVideoDecoderHuffyuv : public IVDVideoDecoderHuffyuv {
  669. public:
  670.     void        Init(uint32 w, uint32 h, uint32 depth, const uint8 *extradata, uint32 extralen);
  671.     void        DecompressFrame(const void *src, uint32 len);
  672.     VDPixmap    GetFrameBuffer();
  673.  
  674. protected:
  675.     uint32        LoadAdaptiveTables(const void *src, uint32 len);
  676.  
  677.     enum FormatMode {
  678.         kFormatMode_YUY2,
  679.         kFormatMode_YV12,
  680.         kFormatMode_RGB,
  681.         kFormatMode_RGBA
  682.     };
  683.  
  684.     enum PredictMode {
  685.         kPredictMode_Default,
  686.         kPredictMode_Left,
  687.         kPredictMode_LeftDecorrelate,
  688.         kPredictMode_Gradient,
  689.         kPredictMode_GradientDecorrelate,
  690.         kPredictMode_Median
  691.     };
  692.  
  693.     PredictMode        mPredictMode;
  694.     FormatMode        mFormatMode;
  695.     bool            mbInterlaced;
  696.     bool            mbAdaptiveHuffman;
  697.  
  698.     VDPixmapBuffer    mFrameBuffer;
  699.  
  700.     HuffmanDecodeTable    mTables[3];
  701.  
  702.     vdfastvector<uint32>    mSafeDecodeArea;
  703. };
  704.  
  705. IVDVideoDecoderHuffyuv *VDCreateVideoDecoderHuffyuv() {
  706.     return new VDVideoDecoderHuffyuv;
  707. }
  708.  
  709. void VDVideoDecoderHuffyuv::Init(uint32 w, uint32 h, uint32 depth, const uint8 *extradata, uint32 extralen) {
  710.     switch(depth & 7) {
  711.         case 0:
  712.         default:
  713.             mPredictMode = kPredictMode_Default;
  714.             break;
  715.  
  716.         case 1:
  717.             mPredictMode = kPredictMode_Left;
  718.             break;
  719.  
  720.         case 2:
  721.             mPredictMode = kPredictMode_LeftDecorrelate;
  722.             break;
  723.  
  724.         case 3:
  725.             mPredictMode = kPredictMode_Gradient;
  726.             break;
  727.  
  728.         case 4:
  729.             mPredictMode = kPredictMode_GradientDecorrelate;
  730.             break;
  731.  
  732.         case 5:
  733.             mPredictMode = kPredictMode_Median;
  734.             break;
  735.     }
  736.  
  737.     mbInterlaced = (h > 288);
  738.     mbAdaptiveHuffman = false;
  739.  
  740.     if (extralen >= 4) {
  741.         uint8 method2 = extradata[0];
  742.         uint8 bpp_override = extradata[1];
  743.  
  744.         // extension: interlace flag
  745.         switch(extradata[2] & 0x30) {
  746.         case 0x10:
  747.             mbInterlaced = true;
  748.             break;
  749.         case 0x20:
  750.             mbInterlaced = false;
  751.             break;
  752.         }
  753.  
  754.         // extension: adaptive Huffman
  755.         mbAdaptiveHuffman = (extradata[2] & 0x40) != 0;
  756.  
  757.         depth = bpp_override;
  758.  
  759.         if (!mPredictMode) {
  760.             switch(method2) {
  761.                 case 0xFE:
  762.                     mPredictMode = kPredictMode_Default;
  763.                     break;
  764.                 case 0x00:
  765.                     mPredictMode = kPredictMode_Left;
  766.                     break;
  767.                 case 0x01:
  768.                     mPredictMode = kPredictMode_Gradient;
  769.                     break;
  770.                 case 0x02:
  771.                     mPredictMode = kPredictMode_Median;
  772.                     break;
  773.                 case 0x40:
  774.                     mPredictMode = kPredictMode_LeftDecorrelate;
  775.                     break;
  776.                 case 0x41:
  777.                     mPredictMode = kPredictMode_GradientDecorrelate;
  778.                     break;
  779.             }
  780.         }
  781.  
  782.         if (extralen >= 4 && !mbAdaptiveHuffman) {
  783.             extradata += 4;
  784.  
  785.             const uint8 *limit = extradata + extralen - 4;
  786.             extradata = mTables[0].Init(extradata, extralen);
  787.             extradata = mTables[1].Init(extradata, limit - extradata);
  788.             extradata = mTables[2].Init(extradata, limit - extradata);
  789.         }
  790.     } else {
  791.         throw MyError("The Huffyuv video stream uses an unsupported old format that lacks embedded encoding tables.");
  792.     }
  793.  
  794.     if (!mPredictMode)
  795.         mPredictMode = kPredictMode_Left;
  796.  
  797.     switch(depth & ~7) {
  798.         case 16:
  799.             mFormatMode = kFormatMode_YUY2;
  800.             mFrameBuffer.init(w, h, nsVDPixmap::kPixFormat_YUV422_YUYV);
  801.             break;
  802.         case 24:
  803.             mFormatMode = kFormatMode_RGB;
  804.             mFrameBuffer.init(w, h, nsVDPixmap::kPixFormat_RGB888);
  805.             break;
  806.         case 32:
  807.             mFormatMode = kFormatMode_RGBA;
  808.             mFrameBuffer.init(w, h, nsVDPixmap::kPixFormat_XRGB8888);
  809.             break;
  810.         case 8:
  811.             if (depth == 12) {
  812.                 mFormatMode = kFormatMode_YV12;
  813.                 mFrameBuffer.init(w, h, nsVDPixmap::kPixFormat_YUV420_Planar);
  814.                 break;
  815.             }
  816.             // fall through
  817.  
  818.         default:
  819.             throw MyError("The Huffyuv video stream uses an unsupported bit depth (%d).", depth);
  820.     }
  821. }
  822.  
  823. void VDVideoDecoderHuffyuv::DecompressFrame(const void *src, uint32 len) {
  824.     uint32 pos = 0;
  825.     if (mbAdaptiveHuffman) {
  826.         uint32 offset = LoadAdaptiveTables(src, len);
  827.  
  828.         pos = offset << 3;
  829.     }
  830.  
  831.     uint32 w = mFrameBuffer.w;
  832.     uint32 h = mFrameBuffer.h;
  833.  
  834.     const uint32 *src32 = (const uint32 *)src;
  835.     uint8 *dstrow = (uint8 *)mFrameBuffer.data;
  836.     ptrdiff_t dstpitch = mFrameBuffer.pitch;
  837.     uint8 *dstrowU = (uint8 *)mFrameBuffer.data2;
  838.     ptrdiff_t dstpitchU = mFrameBuffer.pitch2;
  839.     uint8 *dstrowV = (uint8 *)mFrameBuffer.data3;
  840.     ptrdiff_t dstpitchV = mFrameBuffer.pitch3;
  841.  
  842.     // flip RGB formats
  843.     if (mFormatMode == kFormatMode_RGB || mFormatMode == kFormatMode_RGBA) {
  844.         dstrow += dstpitch * (h - 1);
  845.         dstpitch = -dstpitch;
  846.     } else {
  847.         w >>= 1;
  848.     }
  849.  
  850.     uint8 predictors[4];
  851.     uint32 bpp = 4;
  852.     
  853.     uint32 verticalPredictionStart = mbInterlaced ? 2 : 1;
  854.     ptrdiff_t verticalPredDelta = mbInterlaced ? -2*dstpitch : -dstpitch;
  855.     ptrdiff_t verticalPredDeltaU = mbInterlaced ? -2*dstpitchU : -dstpitchU;
  856.     ptrdiff_t verticalPredDeltaV = mbInterlaced ? -2*dstpitchV : -dstpitchV;
  857.     uint32 *safeDecodeArea = mSafeDecodeArea.data();
  858.     uint32 safeDecodeAreaSizeInDwords = mSafeDecodeArea.size();
  859.     uint32 safeDecodeAreaSizeInBits = safeDecodeAreaSizeInDwords << 5;
  860.     uint32 maxSafePosition = 0;
  861.     uint32 bufferSizeInBits = len << 3;
  862.     uint32 validPosLimit = 0xFFFFFFFFU;
  863.  
  864.     if (bufferSizeInBits > safeDecodeAreaSizeInBits)
  865.         maxSafePosition = bufferSizeInBits - safeDecodeAreaSizeInBits;
  866.  
  867.     for(uint32 y=0; y<h; ++y) {
  868.         if (pos >= maxSafePosition) {
  869.             maxSafePosition = 0xFFFFFFFFU;
  870.  
  871.             uint32 posDwordIdx = pos >> 5;
  872.             uint32 bytesLeft = len - (posDwordIdx << 2);
  873.  
  874.             VDASSERT(bytesLeft <= safeDecodeAreaSizeInDwords * sizeof(uint32));
  875.  
  876.             memcpy(safeDecodeArea, &src32[posDwordIdx], bytesLeft);
  877.             src32 = safeDecodeArea;
  878.             pos &= 31;
  879.             validPosLimit = bytesLeft << 3;
  880.         }
  881.  
  882.         uint8 *dst = dstrow;
  883.         uint8 *dstU = dstrowU;
  884.         uint8 *dstV = dstrowV;
  885.  
  886.         if (!y) {
  887.             uint32 posidx = pos >> 5;
  888.             uint32 bitpos = pos & 31;
  889.             uint32 v = (src32[posidx] << bitpos) + ((src32[posidx + 1] >> (31-bitpos)) >> 1);
  890.  
  891.             if (mFormatMode == kFormatMode_RGB) {
  892.                 uint8 b = (uint8)(v >>  8);
  893.                 uint8 g = (uint8)(v >> 16);
  894.                 uint8 r = (uint8)(v >> 24);
  895.  
  896.                 dstrow[0] = b;
  897.                 dstrow[1] = g;
  898.                 dstrow[2] = r;
  899.  
  900.                 switch (mPredictMode) {
  901.                     case kPredictMode_LeftDecorrelate:
  902.                     case kPredictMode_GradientDecorrelate:
  903.                         r -= g;
  904.                         b -= g;
  905.                         break;
  906.                 }
  907.  
  908.                 predictors[0] = b;
  909.                 predictors[1] = g;
  910.                 predictors[2] = r;
  911.                 bpp = 3;
  912.                 dst += 3;
  913.             } else if (mFormatMode == kFormatMode_RGBA) {
  914.                 uint8 b = (uint8)(v >>  0);
  915.                 uint8 g = (uint8)(v >>  8);
  916.                 uint8 r = (uint8)(v >> 16);
  917.                 uint8 a = (uint8)(v >> 24);
  918.  
  919.                 dstrow[0] = b;
  920.                 dstrow[1] = g;
  921.                 dstrow[2] = r;
  922.                 dstrow[3] = a;
  923.  
  924.                 switch (mPredictMode) {
  925.                     case kPredictMode_LeftDecorrelate:
  926.                     case kPredictMode_GradientDecorrelate:
  927.                         r -= g;
  928.                         b -= g;
  929.                         a -= g;
  930.                         break;
  931.                 }
  932.  
  933.                 predictors[0] = b;
  934.                 predictors[1] = g;
  935.                 predictors[2] = r;
  936.                 predictors[3] = a;
  937.                 bpp = 4;
  938.                 dst += 4;
  939.             } else if (mFormatMode == kFormatMode_YV12) {
  940.                 dstrow[0] = (uint8)(v >>  0);
  941.                 dstrowU[0] = (uint8)(v >>  8);
  942.                 dstrow[1] = (uint8)(v >> 16);
  943.                 dstrowV[0] = (uint8)(v >> 24);
  944.  
  945.                 predictors[0] = dstrow[1];
  946.                 predictors[1] = dstrowU[0];
  947.                 predictors[2] = dstrowV[0];
  948.                 dst += 2;
  949.                 ++dstU;
  950.                 ++dstV;
  951.             } else {
  952.                 dstrow[0] = (uint8)(v >>  0);
  953.                 dstrow[1] = (uint8)(v >>  8);
  954.                 dstrow[2] = (uint8)(v >> 16);
  955.                 dstrow[3] = (uint8)(v >> 24);
  956.  
  957.                 predictors[0] = dstrow[2];
  958.                 predictors[1] = dstrow[1];
  959.                 predictors[2] = dstrow[3];
  960.                 dst += 4;
  961.             }
  962.  
  963.             pos += 32;
  964.         }
  965.  
  966.         if (mFormatMode == kFormatMode_RGB) {
  967.             switch(mPredictMode) {
  968.                 case kPredictMode_Left:
  969.                     pos = DecodeRGBPredictLeft(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  970.                     break;
  971.  
  972.                 case kPredictMode_Gradient:
  973.                     pos = DecodeRGBPredictLeft(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  974.  
  975.                     if (y >= verticalPredictionStart)
  976.                         DecodeVerticalPrediction(dstrow, dstrow + verticalPredDelta, bpp*w);
  977.                     break;
  978.  
  979.                 case kPredictMode_LeftDecorrelate:
  980.                     pos = DecodeRGBPredictLeftDecorr(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  981.                     break;
  982.  
  983.                 case kPredictMode_GradientDecorrelate:
  984.                     pos = DecodeRGBPredictLeftDecorr(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  985.  
  986.                     if (y >= verticalPredictionStart)
  987.                         DecodeVerticalPrediction(dstrow, dstrow + verticalPredDelta, bpp*w);
  988.                     break;
  989.             }
  990.         } else if (mFormatMode == kFormatMode_RGBA) {
  991.             switch(mPredictMode) {
  992.                 case kPredictMode_Left:
  993.                     pos = DecodeRGBAPredictLeft(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  994.                     break;
  995.  
  996.                 case kPredictMode_Gradient:
  997.                     pos = DecodeRGBAPredictLeft(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  998.  
  999.                     if (y >= verticalPredictionStart)
  1000.                         DecodeVerticalPrediction(dstrow, dstrow + verticalPredDelta, bpp*w);
  1001.                     break;
  1002.  
  1003.                 case kPredictMode_LeftDecorrelate:
  1004.                     pos = DecodeRGBAPredictLeftDecorr(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  1005.                     break;
  1006.  
  1007.                 case kPredictMode_GradientDecorrelate:
  1008.                     pos = DecodeRGBAPredictLeftDecorr(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  1009.  
  1010.                     if (y >= verticalPredictionStart)
  1011.                         DecodeVerticalPrediction(dstrow, dstrow + verticalPredDelta, bpp*w);
  1012.                     break;
  1013.             }
  1014.         } else if (mFormatMode == kFormatMode_YV12) {
  1015.             switch(mPredictMode) {
  1016.                 case kPredictMode_Left:
  1017.                     if (y & 1)
  1018.                         pos = DecodeY8PredictLeft(dst, src32, pos, w, mTables, predictors);
  1019.                     else {
  1020.                         pos = DecodeYV12PredictLeft(dst, dstU, dstV, src32, pos, y ? w : w - 1, mTables, predictors);
  1021.  
  1022.                         dstrowU += dstpitchU;
  1023.                         dstrowV += dstpitchV;
  1024.                     }
  1025.                     break;
  1026.  
  1027.                 case kPredictMode_Gradient:
  1028.                     if (y & 1) {
  1029.                         pos = DecodeY8PredictLeft(dst, src32, pos, w, mTables, predictors);
  1030.  
  1031.                         if (y >= verticalPredictionStart)
  1032.                             DecodeVerticalPrediction(dstrow, dstrow + verticalPredDelta, w*2);
  1033.                     } else {
  1034.                         pos = DecodeYV12PredictLeft(dst, dstU, dstV, src32, pos, y ? w : w - 1, mTables, predictors);
  1035.  
  1036.                         if (y >= verticalPredictionStart) {
  1037.                             DecodeVerticalPrediction(dstrow, dstrow + verticalPredDelta, w*2);
  1038.                             DecodeVerticalPrediction(dstrowU, dstrowU + verticalPredDeltaU, w);
  1039.                             DecodeVerticalPrediction(dstrowV, dstrowV + verticalPredDeltaV, w);
  1040.                         }
  1041.  
  1042.                         dstrowU += dstpitchU;
  1043.                         dstrowV += dstpitchV;
  1044.                     }
  1045.                     break;
  1046.  
  1047.                 case kPredictMode_Median:
  1048.                     // Whoever created the median mode for the YV12 variant was clearly smoking crack, because
  1049.                     // chroma is interleaved with luma at approximately every other line, but there is an anomaly
  1050.                     // at the beginning of the file where either the first two or four lines of the stream are
  1051.                     // all YCbCr lines, followed by two or four lines of just Y.
  1052.  
  1053.                     if (y < verticalPredictionStart) {
  1054.                         // The first line (non-interlaced) or two lines (interlaced) are just left predicted but
  1055.                         // fully YCbCr encoded.
  1056.                         pos = DecodeYV12PredictLeft(dst, dstU, dstV, src32, pos, y ? w : w - 1, mTables, predictors);
  1057.                         dstrowU += dstpitchU;
  1058.                         dstrowV += dstpitchV;
  1059.                     } else if (y == verticalPredictionStart) {
  1060.                         // Line 1 (ni) or 2 (i) is left predicted for the first four pixels, then median encoded.
  1061.                         // Full YCbCr encoding.
  1062.                         pos = DecodeYV12(dst, dstU, dstV, src32, pos, w, mTables);
  1063.  
  1064.                         dstrow[0] += predictors[0];
  1065.                         dstrow[1] += dstrow[0];
  1066.                         dstrow[2] += dstrow[1];
  1067.                         dstrow[3] += dstrow[2];
  1068.                         
  1069.                         DecodeMedianPredictionY8(dstrow + 4, dstrow + 3, dstrow + verticalPredDelta + 4, dstrow + verticalPredDelta + 3, w*2 - 4);
  1070.  
  1071.                         dstrowU[0] += predictors[1];
  1072.                         dstrowU[1] += dstrowU[0];
  1073.                         
  1074.                         DecodeMedianPredictionY8(dstrowU + 2, dstrowU + 1, dstrowU + verticalPredDeltaU + 2, dstrowU + verticalPredDeltaU + 1, w - 2);
  1075.  
  1076.                         dstrowV[0] += predictors[2];
  1077.                         dstrowV[1] += dstrowV[0];
  1078.                         
  1079.                         DecodeMedianPredictionY8(dstrowV + 2, dstrowV + 1, dstrowV + verticalPredDeltaV + 2, dstrowV + verticalPredDeltaV + 1, w - 2);
  1080.  
  1081.                         dstrowU += dstpitchU;
  1082.                         dstrowV += dstpitchV;
  1083.                     } else if ((y & 1) || y < verticalPredictionStart * 2 + 2) {
  1084.                         pos = DecodeY8(dst, src32, pos, w, mTables);
  1085.  
  1086.                         DecodeMedianPredictionY8(dstrow, dstrow - dstpitch + w*2 - 1, dstrow + verticalPredDelta, dstrow + verticalPredDelta - dstpitch + w*2 - 1, 1);
  1087.                         DecodeMedianPredictionY8(dstrow + 1, dstrow, dstrow + verticalPredDelta + 1, dstrow + verticalPredDelta, w*2 - 1);
  1088.                     } else {
  1089.                         pos = DecodeYV12(dst, dstU, dstV, src32, pos, w, mTables);
  1090.  
  1091.                         DecodeMedianPredictionY8(dstrow, dstrow - dstpitch + w*2 - 1, dstrow + verticalPredDelta, dstrow + verticalPredDelta - dstpitch + w*2 - 1, 1);
  1092.                         DecodeMedianPredictionY8(dstrow + 1, dstrow, dstrow + verticalPredDelta + 1, dstrow + verticalPredDelta, 2*w - 1);
  1093.  
  1094.                         DecodeMedianPredictionY8(dstrowU, dstrowU - dstpitchU + w - 1, dstrowU + verticalPredDeltaU, dstrowU + verticalPredDeltaU - dstpitchU + w - 1, 1);
  1095.                         DecodeMedianPredictionY8(dstrowU + 1, dstrowU, dstrowU + verticalPredDeltaU + 1, dstrowU + verticalPredDeltaU, w - 1);
  1096.  
  1097.                         DecodeMedianPredictionY8(dstrowV, dstrowV - dstpitchV + w - 1, dstrowV + verticalPredDeltaV, dstrowV + verticalPredDeltaV - dstpitchV + w - 1, 1);
  1098.                         DecodeMedianPredictionY8(dstrowV + 1, dstrowV, dstrowV + verticalPredDeltaV + 1, dstrowV + verticalPredDeltaV, w - 1);
  1099.  
  1100.                         dstrowU += dstpitchU;
  1101.                         dstrowV += dstpitchV;
  1102.                     }
  1103.                     break;
  1104.             }
  1105.         } else {
  1106.             switch(mPredictMode) {
  1107.                 case kPredictMode_Left:
  1108.                     pos = DecodeYUY2PredictLeft(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  1109.                     break;
  1110.  
  1111.                 case kPredictMode_Gradient:
  1112.                     pos = DecodeYUY2PredictLeft(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  1113.  
  1114.                     if (y >= verticalPredictionStart)
  1115.                         DecodeVerticalPrediction(dstrow, dstrow + verticalPredDelta, bpp*w);
  1116.                     break;
  1117.  
  1118.                 case kPredictMode_Median:
  1119.                     if (y < verticalPredictionStart) {
  1120.                         pos = DecodeYUY2PredictLeft(dst, src32, pos, y ? w : w - 1, mTables, predictors);
  1121.                     } else {
  1122.                         pos = DecodeYUY2(dst, src32, pos, w, mTables);
  1123.  
  1124.                         if (y > verticalPredictionStart) {
  1125.                             DecodeMedianPredictionYUY2(dstrow, dstrow - dstpitch + w*4 - 4, dstrow + verticalPredDelta, dstrow + verticalPredDelta - dstpitch + w*4 - 4, 1);
  1126.                             DecodeMedianPredictionYUY2(dstrow + 4, dstrow, dstrow + verticalPredDelta + 4, dstrow + verticalPredDelta, w - 1);
  1127.                         } else {
  1128.                             dstrow[0] += predictors[0];
  1129.                             dstrow[1] += predictors[1];
  1130.                             dstrow[2] += dstrow[0];
  1131.                             dstrow[3] += predictors[2];
  1132.                             dstrow[4] += dstrow[2];
  1133.                             dstrow[5] += dstrow[1];
  1134.                             dstrow[6] += dstrow[4];
  1135.                             dstrow[7] += dstrow[3];
  1136.                             
  1137.                             DecodeMedianPredictionYUY2(dstrow + 8, dstrow + 4, dstrow + verticalPredDelta + 8, dstrow + verticalPredDelta + 4, w - 2);
  1138.                         }
  1139.                     }
  1140.                     break;
  1141.             }
  1142.         }
  1143.  
  1144.         dstrow += dstpitch;
  1145.  
  1146.         if (pos > validPosLimit)
  1147.             throw MyError("A decompression error occurred while decoding Huffyuv data.");
  1148.     }
  1149. }
  1150.  
  1151. VDPixmap VDVideoDecoderHuffyuv::GetFrameBuffer() {
  1152.     return mFrameBuffer;
  1153. }
  1154.  
  1155. uint32 VDVideoDecoderHuffyuv::LoadAdaptiveTables(const void *src, uint32 len) {
  1156.     uint32 tmpArea[192];
  1157.     uint32 dwords = len >> 2;
  1158.  
  1159.     if (dwords > 192)
  1160.         dwords = 192;
  1161.  
  1162.     const uint32 *src32 = (uint32 *)src;
  1163.     for(uint32 i=0; i<dwords; ++i)
  1164.         tmpArea[i] = VDSwizzleU32(src32[i]);
  1165.  
  1166.     const uint8 *extradata = (const uint8 *)tmpArea;
  1167.     const uint8 *limit = extradata + 4*dwords;
  1168.  
  1169.     extradata = mTables[0].Init(extradata, limit - extradata);
  1170.     extradata = mTables[1].Init(extradata, limit - extradata);
  1171.     extradata = mTables[2].Init(extradata, limit - extradata);
  1172.  
  1173.     // Compute size of safe decode area.
  1174.     //
  1175.     // We need up to:
  1176.     //    4 bytes for the first pixel
  1177.     //    N bits for VLC coding for each pixel in the row
  1178.     //    31 bits of VLC padding
  1179.     //    32 bits for readover
  1180.     uint32 safeDecAreaSize = sizeof(uint32);
  1181.     uint32 maxBitsChannel0 = mTables[0].mBaseLen;
  1182.     uint32 maxBitsChannel1 = mTables[1].mBaseLen;
  1183.     uint32 maxBitsChannel2 = mTables[2].mBaseLen;
  1184.     uint32 blocks = mFrameBuffer.w;
  1185.  
  1186.     if (mFormatMode == kFormatMode_YUY2 || mFormatMode == kFormatMode_YV12) {
  1187.         maxBitsChannel0 += maxBitsChannel0;
  1188.         blocks >>= 1;
  1189.     }
  1190.  
  1191.     uint32 maxBitsInRow = (maxBitsChannel0 + maxBitsChannel1 + maxBitsChannel2) * blocks;
  1192.     uint32 maxDwordsInRow = ((maxBitsInRow + 31) >> 5) + 2;
  1193.  
  1194.     mSafeDecodeArea.resize(maxDwordsInRow);
  1195.  
  1196.     return extradata - (const uint8 *)tmpArea;
  1197. }
  1198.