/**
 * TheoraPlay; multithreaded Ogg Theora/Ogg Vorbis decoding.
 *
 * Please see the file LICENSE.txt in the source's root directory.
 *
 *  This file written by Ryan C. Gordon.
 */

#if !THEORAPLAY_INTERNAL
#error Do not include this in your app. It is used internally by TheoraPlay.
#endif

static unsigned char *THEORAPLAY_CVT_FNNAME_420(const th_info *tinfo,
                                                const th_ycbcr_buffer ycbcr)
{
    const int w = tinfo->pic_width;
    const int h = tinfo->pic_height;
    unsigned char *pixels = (unsigned char *) malloc(w * h * 4);
    if (pixels)
    {
        unsigned char *dst = pixels;
        const int ystride = ycbcr[0].stride;
        const int cbstride = ycbcr[1].stride;
        const int crstride = ycbcr[2].stride;
        const int yoff = (tinfo->pic_x & ~1) + ystride * (tinfo->pic_y & ~1);
        const int cboff = (tinfo->pic_x / 2) + (cbstride) * (tinfo->pic_y / 2);
        const unsigned char *py = ycbcr[0].data + yoff;
        const unsigned char *pcb = ycbcr[1].data + cboff;
        const unsigned char *pcr = ycbcr[2].data + cboff;
        int posx, posy;

        for (posy = 0; posy < h; posy++)
        {
            for (posx = 0; posx < w; posx++)
            {
                // http://www.theora.org/doc/Theora.pdf, 1.1 spec,
                //  chapter 4.2 (Y'CbCr -> Y'PbPr -> R'G'B')
                // These constants apparently work for NTSC _and_ PAL/SECAM.
                const float yoffset = 16.0f;
                const float yexcursion = 219.0f;
                const float cboffset = 128.0f;
                const float cbexcursion = 224.0f;
                const float croffset = 128.0f;
                const float crexcursion = 224.0f;
                const float kr = 0.299f;
                const float kb = 0.114f;

                const float y = (((float) py[posx]) - yoffset) / yexcursion;
                const float pb = (((float) pcb[posx / 2]) - cboffset) / cbexcursion;
                const float pr = (((float) pcr[posx / 2]) - croffset) / crexcursion;
                const float r = (y + (2.0f * (1.0f - kr) * pr)) * 255.0f;
                const float g = (y - ((2.0f * (((1.0f - kb) * kb) / ((1.0f - kb) - kr))) * pb) - ((2.0f * (((1.0f - kr) * kr) / ((1.0f - kb) - kr))) * pr)) * 255.0f;
                const float b = (y + (2.0f * (1.0f - kb) * pb)) * 255.0f;

                *(dst++) = (unsigned char) ((r < 0.0f) ? 0.0f : (r > 255.0f) ? 255.0f : r);
                *(dst++) = (unsigned char) ((g < 0.0f) ? 0.0f : (g > 255.0f) ? 255.0f : g);
                *(dst++) = (unsigned char) ((b < 0.0f) ? 0.0f : (b > 255.0f) ? 255.0f : b);
                #if THEORAPLAY_CVT_RGB_ALPHA
                *(dst++) = 0xFF;
                #endif
            } // for

            // adjust to the start of the next line.
            py += ystride;
            pcb += cbstride * (posy % 2);
            pcr += crstride * (posy % 2);
        } // for
    } // if

    return pixels;
} // THEORAPLAY_CVT_FNNAME_420

// end of theoraplay_cvtrgb.h ...

