static int flic_decode_frame_8BPP(AVCodecContext *avctx,

                                  void *data, int *data_size,

                                  const uint8_t *buf, int buf_size)

{

    FlicDecodeContext *s = avctx->priv_data;

    int stream_ptr = 0;

    int pixel_ptr;

    int palette_ptr;

    unsigned char palette_idx1;

    unsigned char palette_idx2;

    unsigned int frame_size;

    int num_chunks;

    unsigned int chunk_size;

    int chunk_type;

    int i, j;

    int color_packets;

    int color_changes;

    int color_shift;

    unsigned char r, g, b;

    int lines;

    int compressed_lines;

    int starting_line;

    signed short line_packets;

    int y_ptr;

    int byte_run;

    int pixel_skip;

    int pixel_countdown;

    unsigned char *pixels;

    unsigned int pixel_limit;

    s->frame.reference = 3;

    s->frame.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;

    if (avctx->reget_buffer(avctx, &s->frame) < 0) {

        av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n");

        return -1;

    }

    pixels = s->frame.data[0];

    pixel_limit = s->avctx->height * s->frame.linesize[0];

    if (buf_size < 16 || buf_size > INT_MAX - (3 * 256 + FF_INPUT_BUFFER_PADDING_SIZE))

        return AVERROR_INVALIDDATA;

    frame_size = AV_RL32(&buf[stream_ptr]);

    if (frame_size > buf_size)

        frame_size = buf_size;

    stream_ptr += 6;  /* skip the magic number */

    num_chunks = AV_RL16(&buf[stream_ptr]);

    stream_ptr += 10;  /* skip padding */

    frame_size -= 16;

    /* iterate through the chunks */

    while ((frame_size >= 6) && (num_chunks > 0)) {

        int stream_ptr_after_chunk;

        chunk_size = AV_RL32(&buf[stream_ptr]);

        if (chunk_size > frame_size) {

            av_log(avctx, AV_LOG_WARNING,

                   "Invalid chunk_size = %u > frame_size = %u\n", chunk_size, frame_size);

            chunk_size = frame_size;

        }

        stream_ptr_after_chunk = stream_ptr + chunk_size;

        stream_ptr += 4;

        chunk_type = AV_RL16(&buf[stream_ptr]);

        stream_ptr += 2;

        switch (chunk_type) {

        case FLI_256_COLOR:

        case FLI_COLOR:

            /* check special case: If this file is from the Magic Carpet

             * game and uses 6-bit colors even though it reports 256-color

             * chunks in a 0xAF12-type file (fli_type is set to 0xAF13 during

             * initialization) */

            if ((chunk_type == FLI_256_COLOR) && (s->fli_type != FLC_MAGIC_CARPET_SYNTHETIC_TYPE_CODE))

                color_shift = 0;

            else

                color_shift = 2;

            /* set up the palette */

            color_packets = AV_RL16(&buf[stream_ptr]);

            stream_ptr += 2;

            palette_ptr = 0;

            for (i = 0; i < color_packets; i++) {

                /* first byte is how many colors to skip */

                palette_ptr += buf[stream_ptr++];

                /* next byte indicates how many entries to change */

                color_changes = buf[stream_ptr++];

                /* if there are 0 color changes, there are actually 256 */

                if (color_changes == 0)

                    color_changes = 256;

                if (stream_ptr + color_changes * 3 > stream_ptr_after_chunk)

                    break;

                for (j = 0; j < color_changes; j++) {

                    unsigned int entry;

                    /* wrap around, for good measure */

                    if ((unsigned)palette_ptr >= 256)

                        palette_ptr = 0;

                    r = buf[stream_ptr++] << color_shift;

                    g = buf[stream_ptr++] << color_shift;

                    b = buf[stream_ptr++] << color_shift;

                    entry = 0xFF << 24 | r << 16 | g << 8 | b;

                    if (color_shift == 2)

                        entry |= entry >> 6 & 0x30303;

                    if (s->palette[palette_ptr] != entry)

                        s->new_palette = 1;

                    s->palette[palette_ptr++] = entry;

                }

            }

            break;

        case FLI_DELTA:

            y_ptr = 0;

            compressed_lines = AV_RL16(&buf[stream_ptr]);

            stream_ptr += 2;

            while (compressed_lines > 0) {

                if (stream_ptr + 2 > stream_ptr_after_chunk)

                    break;

                line_packets = AV_RL16(&buf[stream_ptr]);

                stream_ptr += 2;

                if ((line_packets & 0xC000) == 0xC000) {

                    // line skip opcode

                    line_packets = -line_packets;

                    y_ptr += line_packets * s->frame.linesize[0];

                } else if ((line_packets & 0xC000) == 0x4000) {

                    av_log(avctx, AV_LOG_ERROR, "Undefined opcode (%x) in DELTA_FLI\n", line_packets);

                } else if ((line_packets & 0xC000) == 0x8000) {

                    // "last byte" opcode

                    pixel_ptr= y_ptr + s->frame.linesize[0] - 1;

                    CHECK_PIXEL_PTR(0);

                    pixels[pixel_ptr] = line_packets & 0xff;

                } else {

                    compressed_lines--;

                    pixel_ptr = y_ptr;

                    CHECK_PIXEL_PTR(0);

                    pixel_countdown = s->avctx->width;

                    for (i = 0; i < line_packets; i++) {

                        if (stream_ptr + 2 > stream_ptr_after_chunk)

                            break;

                        /* account for the skip bytes */

                        pixel_skip = buf[stream_ptr++];

                        pixel_ptr += pixel_skip;

                        pixel_countdown -= pixel_skip;

                        byte_run = (signed char)(buf[stream_ptr++]);

                        if (byte_run < 0) {

                            byte_run = -byte_run;

                            palette_idx1 = buf[stream_ptr++];

                            palette_idx2 = buf[stream_ptr++];

                            CHECK_PIXEL_PTR(byte_run * 2);

                            for (j = 0; j < byte_run; j++, pixel_countdown -= 2) {

                                pixels[pixel_ptr++] = palette_idx1;

                                pixels[pixel_ptr++] = palette_idx2;

                            }

                        } else {

                            CHECK_PIXEL_PTR(byte_run * 2);

                            if (stream_ptr + byte_run * 2 > stream_ptr_after_chunk)

                                break;

                            for (j = 0; j < byte_run * 2; j++, pixel_countdown--) {

                                palette_idx1 = buf[stream_ptr++];

                                pixels[pixel_ptr++] = palette_idx1;

                            }

                        }

                    }

                    y_ptr += s->frame.linesize[0];

                }

            }

            break;

        case FLI_LC:

            /* line compressed */

            starting_line = AV_RL16(&buf[stream_ptr]);

            stream_ptr += 2;

            y_ptr = 0;

            y_ptr += starting_line * s->frame.linesize[0];

            compressed_lines = AV_RL16(&buf[stream_ptr]);

            stream_ptr += 2;

            while (compressed_lines > 0) {

                pixel_ptr = y_ptr;

                CHECK_PIXEL_PTR(0);

                pixel_countdown = s->avctx->width;

                line_packets = buf[stream_ptr++];

                if (stream_ptr + 2 * line_packets > stream_ptr_after_chunk)

                    break;

                if (line_packets > 0) {

                    for (i = 0; i < line_packets; i++) {

                        /* account for the skip bytes */

                        pixel_skip = buf[stream_ptr++];

                        pixel_ptr += pixel_skip;

                        pixel_countdown -= pixel_skip;

                        byte_run = (signed char)(buf[stream_ptr++]);

                        if (byte_run > 0) {

                            CHECK_PIXEL_PTR(byte_run);

                            if (stream_ptr + byte_run > stream_ptr_after_chunk)

                                break;

                            for (j = 0; j < byte_run; j++, pixel_countdown--) {

                                palette_idx1 = buf[stream_ptr++];

                                pixels[pixel_ptr++] = palette_idx1;

                            }

                        } else if (byte_run < 0) {

                            byte_run = -byte_run;

                            palette_idx1 = buf[stream_ptr++];

                            CHECK_PIXEL_PTR(byte_run);

                            for (j = 0; j < byte_run; j++, pixel_countdown--) {

                                pixels[pixel_ptr++] = palette_idx1;

                            }

                        }

                    }

                }

                y_ptr += s->frame.linesize[0];

                compressed_lines--;

            }

            break;

        case FLI_BLACK:

            /* set the whole frame to color 0 (which is usually black) */

            memset(pixels, 0,

                s->frame.linesize[0] * s->avctx->height);

            break;

        case FLI_BRUN:

            /* Byte run compression: This chunk type only occurs in the first

             * FLI frame and it will update the entire frame. */

            y_ptr = 0;

            for (lines = 0; lines < s->avctx->height; lines++) {

                pixel_ptr = y_ptr;

                /* disregard the line packets; instead, iterate through all

                 * pixels on a row */

                stream_ptr++;

                pixel_countdown = s->avctx->width;

                while (pixel_countdown > 0) {

                    if (stream_ptr + 1 > stream_ptr_after_chunk)

                        break;

                    byte_run = (signed char)(buf[stream_ptr++]);

                    if (byte_run > 0) {

                        palette_idx1 = buf[stream_ptr++];

                        CHECK_PIXEL_PTR(byte_run);

                        for (j = 0; j < byte_run; j++) {

                            pixels[pixel_ptr++] = palette_idx1;

                            pixel_countdown--;

                            if (pixel_countdown < 0)

                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",

                                       pixel_countdown, lines);

                        }

                    } else {  /* copy bytes if byte_run < 0 */

                        byte_run = -byte_run;

                        CHECK_PIXEL_PTR(byte_run);

                        if (stream_ptr + byte_run > stream_ptr_after_chunk)

                            break;

                        for (j = 0; j < byte_run; j++) {

                            palette_idx1 = buf[stream_ptr++];

                            pixels[pixel_ptr++] = palette_idx1;

                            pixel_countdown--;

                            if (pixel_countdown < 0)

                                av_log(avctx, AV_LOG_ERROR, "pixel_countdown < 0 (%d) at line %d\n",

                                       pixel_countdown, lines);

                        }

                    }

                }

                y_ptr += s->frame.linesize[0];

            }

            break;

        case FLI_COPY:

            /* copy the chunk (uncompressed frame) */

            if (chunk_size - 6 != s->avctx->width * s->avctx->height) {

                av_log(avctx, AV_LOG_ERROR, "In chunk FLI_COPY : source data (%d bytes) " \

                       "has incorrect size, skipping chunk\n", chunk_size - 6);

            } else {

                for (y_ptr = 0; y_ptr < s->frame.linesize[0] * s->avctx->height;

                     y_ptr += s->frame.linesize[0]) {

                    memcpy(&pixels[y_ptr], &buf[stream_ptr],

                        s->avctx->width);

                    stream_ptr += s->avctx->width;

                }

            }

            break;

        case FLI_MINI:

            /* some sort of a thumbnail? disregard this chunk... */

            break;

        default:

            av_log(avctx, AV_LOG_ERROR, "Unrecognized chunk type: %d\n", chunk_type);

            break;

        }

        stream_ptr = stream_ptr_after_chunk;

        frame_size -= chunk_size;

        num_chunks--;

    }

    /* by the end of the chunk, the stream ptr should equal the frame

     * size (minus 1, possibly); if it doesn't, issue a warning */

    if ((stream_ptr != buf_size) && (stream_ptr != buf_size - 1))

        av_log(avctx, AV_LOG_ERROR, "Processed FLI chunk where chunk size = %d " \

               "and final chunk ptr = %d\n", buf_size, stream_ptr);

    /* make the palette available on the way out */

    memcpy(s->frame.data[1], s->palette, AVPALETTE_SIZE);

    if (s->new_palette) {

        s->frame.palette_has_changed = 1;

        s->new_palette = 0;

    }

    *data_size=sizeof(AVFrame);

    *(AVFrame*)data = s->frame;

    return buf_size;

}


static int dcstr_read_header(AVFormatContext *s)

{

    unsigned codec, align;

    AVStream *st;

    st = avformat_new_stream(s, NULL);

    if (!st)

        return AVERROR(ENOMEM);

    st->codecpar->codec_type  = AVMEDIA_TYPE_AUDIO;

    st->codecpar->channels    = avio_rl32(s->pb);

    st->codecpar->sample_rate = avio_rl32(s->pb);

    codec                  = avio_rl32(s->pb);

    align                  = avio_rl32(s->pb);

    avio_skip(s->pb, 4);

    st->duration           = avio_rl32(s->pb);

    st->codecpar->channels   *= avio_rl32(s->pb);

    if (!align || align > INT_MAX / st->codecpar->channels)

        return AVERROR_INVALIDDATA;

    st->codecpar->block_align = align * st->codecpar->channels;

    switch (codec) {

    case  4: st->codecpar->codec_id = AV_CODEC_ID_ADPCM_AICA;       break;

    case 16: st->codecpar->codec_id = AV_CODEC_ID_PCM_S16LE_PLANAR; break;

    default: avpriv_request_sample(s, "codec %X", codec);

             return AVERROR_PATCHWELCOME;

    }

    avio_skip(s->pb, 0x800 - avio_tell(s->pb));

    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);

    return 0;

}


int ff_oss_audio_open(AVFormatContext *s1, int is_output,

                      const char *audio_device)

{

    OSSAudioData *s = s1->priv_data;

    int audio_fd;

    int tmp, err;

    char *flip = getenv("AUDIO_FLIP_LEFT");

    if (is_output)

        audio_fd = avpriv_open(audio_device, O_WRONLY);

    else

        audio_fd = avpriv_open(audio_device, O_RDONLY);

    if (audio_fd < 0) {

        av_log(s1, AV_LOG_ERROR, "%s: %s\n", audio_device, strerror(errno));

        return AVERROR(EIO);

    }

    if (flip && *flip == '1') {

        s->flip_left = 1;

    }

    /* non blocking mode */

    if (!is_output)

        fcntl(audio_fd, F_SETFL, O_NONBLOCK);

    s->frame_size = OSS_AUDIO_BLOCK_SIZE;

    /* select format : favour native format */

    err = ioctl(audio_fd, SNDCTL_DSP_GETFMTS, &tmp);

#if HAVE_BIGENDIAN

    if (tmp & AFMT_S16_BE) {

        tmp = AFMT_S16_BE;

    } else if (tmp & AFMT_S16_LE) {

        tmp = AFMT_S16_LE;

    } else {

        tmp = 0;

    }

#else

    if (tmp & AFMT_S16_LE) {

        tmp = AFMT_S16_LE;

    } else if (tmp & AFMT_S16_BE) {

        tmp = AFMT_S16_BE;

    } else {

        tmp = 0;

    }

#endif

    switch(tmp) {

    case AFMT_S16_LE:

        s->codec_id = AV_CODEC_ID_PCM_S16LE;

        break;

    case AFMT_S16_BE:

        s->codec_id = AV_CODEC_ID_PCM_S16BE;

        break;

    default:

        av_log(s1, AV_LOG_ERROR, "Soundcard does not support 16 bit sample format\n");

        close(audio_fd);

        return AVERROR(EIO);

    }

    err=ioctl(audio_fd, SNDCTL_DSP_SETFMT, &tmp);

    if (err < 0) {

        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SETFMT: %s\n", strerror(errno));

        goto fail;

    }

    tmp = (s->channels == 2);

    err = ioctl(audio_fd, SNDCTL_DSP_STEREO, &tmp);

    if (err < 0) {

        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_STEREO: %s\n", strerror(errno));

        goto fail;

    }

    tmp = s->sample_rate;

    err = ioctl(audio_fd, SNDCTL_DSP_SPEED, &tmp);

    if (err < 0) {

        av_log(s1, AV_LOG_ERROR, "SNDCTL_DSP_SPEED: %s\n", strerror(errno));

        goto fail;

    }

    s->sample_rate = tmp; /* store real sample rate */

    s->fd = audio_fd;

    return 0;

 fail:

    close(audio_fd);

    return AVERROR(EIO);

}


static int RENAME(swScale)(SwsContext *c, uint8_t* src[], int srcStride[], int srcSliceY,

                           int srcSliceH, uint8_t* dst[], int dstStride[])

{

    /* load a few things into local vars to make the code more readable? and faster */

    const int srcW= c->srcW;

    const int dstW= c->dstW;

    const int dstH= c->dstH;

    const int chrDstW= c->chrDstW;

    const int chrSrcW= c->chrSrcW;

    const int lumXInc= c->lumXInc;

    const int chrXInc= c->chrXInc;

    const enum PixelFormat dstFormat= c->dstFormat;

    const enum PixelFormat srcFormat= c->srcFormat;

    const int flags= c->flags;

    int16_t *vLumFilterPos= c->vLumFilterPos;

    int16_t *vChrFilterPos= c->vChrFilterPos;

    int16_t *hLumFilterPos= c->hLumFilterPos;

    int16_t *hChrFilterPos= c->hChrFilterPos;

    int16_t *vLumFilter= c->vLumFilter;

    int16_t *vChrFilter= c->vChrFilter;

    int16_t *hLumFilter= c->hLumFilter;

    int16_t *hChrFilter= c->hChrFilter;

    int32_t *lumMmxFilter= c->lumMmxFilter;

    int32_t *chrMmxFilter= c->chrMmxFilter;

    int32_t *alpMmxFilter= c->alpMmxFilter;

    const int vLumFilterSize= c->vLumFilterSize;

    const int vChrFilterSize= c->vChrFilterSize;

    const int hLumFilterSize= c->hLumFilterSize;

    const int hChrFilterSize= c->hChrFilterSize;

    int16_t **lumPixBuf= c->lumPixBuf;

    int16_t **chrPixBuf= c->chrPixBuf;

    int16_t **alpPixBuf= c->alpPixBuf;

    const int vLumBufSize= c->vLumBufSize;

    const int vChrBufSize= c->vChrBufSize;

    uint8_t *formatConvBuffer= c->formatConvBuffer;

    const int chrSrcSliceY= srcSliceY >> c->chrSrcVSubSample;

    const int chrSrcSliceH= -((-srcSliceH) >> c->chrSrcVSubSample);

    int lastDstY;

    uint32_t *pal=c->pal_yuv;

    /* vars which will change and which we need to store back in the context */

    int dstY= c->dstY;

    int lumBufIndex= c->lumBufIndex;

    int chrBufIndex= c->chrBufIndex;

    int lastInLumBuf= c->lastInLumBuf;

    int lastInChrBuf= c->lastInChrBuf;

    if (isPacked(c->srcFormat)) {

        src[0]=

        src[1]=

        src[2]=

        src[3]= src[0];

        srcStride[0]=

        srcStride[1]=

        srcStride[2]=

        srcStride[3]= srcStride[0];

    }

    srcStride[1]<<= c->vChrDrop;

    srcStride[2]<<= c->vChrDrop;

    DEBUG_BUFFERS("swScale() %p[%d] %p[%d] %p[%d] %p[%d] -> %p[%d] %p[%d] %p[%d] %p[%d]\n",

                  src[0], srcStride[0], src[1], srcStride[1], src[2], srcStride[2], src[3], srcStride[3],

                  dst[0], dstStride[0], dst[1], dstStride[1], dst[2], dstStride[2], dst[3], dstStride[3]);

    DEBUG_BUFFERS("srcSliceY: %d srcSliceH: %d dstY: %d dstH: %d\n",

                   srcSliceY,    srcSliceH,    dstY,    dstH);

    DEBUG_BUFFERS("vLumFilterSize: %d vLumBufSize: %d vChrFilterSize: %d vChrBufSize: %d\n",

                   vLumFilterSize,    vLumBufSize,    vChrFilterSize,    vChrBufSize);

    if (dstStride[0]%8 !=0 || dstStride[1]%8 !=0 || dstStride[2]%8 !=0 || dstStride[3]%8 != 0) {

        static int warnedAlready=0; //FIXME move this into the context perhaps

        if (flags & SWS_PRINT_INFO && !warnedAlready) {

            av_log(c, AV_LOG_WARNING, "Warning: dstStride is not aligned!\n"

                   "         ->cannot do aligned memory accesses anymore\n");

            warnedAlready=1;

        }

    }

    /* Note the user might start scaling the picture in the middle so this

       will not get executed. This is not really intended but works

       currently, so people might do it. */

    if (srcSliceY ==0) {

        lumBufIndex=0;

        chrBufIndex=0;

        dstY=0;

        lastInLumBuf= -1;

        lastInChrBuf= -1;

    }

    lastDstY= dstY;

    for (;dstY < dstH; dstY++) {

        unsigned char *dest =dst[0]+dstStride[0]*dstY;

        const int chrDstY= dstY>>c->chrDstVSubSample;

        unsigned char *uDest=dst[1]+dstStride[1]*chrDstY;

        unsigned char *vDest=dst[2]+dstStride[2]*chrDstY;

        unsigned char *aDest=(CONFIG_SWSCALE_ALPHA && alpPixBuf) ? dst[3]+dstStride[3]*dstY : NULL;

        const int firstLumSrcY= vLumFilterPos[dstY]; //First line needed as input

        const int firstChrSrcY= vChrFilterPos[chrDstY]; //First line needed as input

        int lastLumSrcY= firstLumSrcY + vLumFilterSize -1; // Last line needed as input

        int lastChrSrcY= firstChrSrcY + vChrFilterSize -1; // Last line needed as input

        int enough_lines;

        //handle holes (FAST_BILINEAR & weird filters)

        if (firstLumSrcY > lastInLumBuf) lastInLumBuf= firstLumSrcY-1;

        if (firstChrSrcY > lastInChrBuf) lastInChrBuf= firstChrSrcY-1;

        assert(firstLumSrcY >= lastInLumBuf - vLumBufSize + 1);

        assert(firstChrSrcY >= lastInChrBuf - vChrBufSize + 1);

        // Do we have enough lines in this slice to output the dstY line

        enough_lines = lastLumSrcY < srcSliceY + srcSliceH && lastChrSrcY < -((-srcSliceY - srcSliceH)>>c->chrSrcVSubSample);

        if (!enough_lines) {

            lastLumSrcY = srcSliceY + srcSliceH - 1;

            lastChrSrcY = chrSrcSliceY + chrSrcSliceH - 1;

        }

        DEBUG_BUFFERS("dstY: %d\n", dstY);

        DEBUG_BUFFERS("\tfirstLumSrcY: %d lastLumSrcY: %d lastInLumBuf: %d\n",

                         firstLumSrcY,    lastLumSrcY,    lastInLumBuf);

        DEBUG_BUFFERS("\tfirstChrSrcY: %d lastChrSrcY: %d lastInChrBuf: %d\n",

                         firstChrSrcY,    lastChrSrcY,    lastInChrBuf);

        //Do horizontal scaling

        while(lastInLumBuf < lastLumSrcY) {

            uint8_t *src1= src[0]+(lastInLumBuf + 1 - srcSliceY)*srcStride[0];

            uint8_t *src2= src[3]+(lastInLumBuf + 1 - srcSliceY)*srcStride[3];

            lumBufIndex++;

            DEBUG_BUFFERS("\t\tlumBufIndex %d: lastInLumBuf: %d\n",

                               lumBufIndex,    lastInLumBuf);

            assert(lumBufIndex < 2*vLumBufSize);

            assert(lastInLumBuf + 1 - srcSliceY < srcSliceH);

            assert(lastInLumBuf + 1 - srcSliceY >= 0);

            RENAME(hyscale)(c, lumPixBuf[ lumBufIndex ], dstW, src1, srcW, lumXInc,

                            flags, hLumFilter, hLumFilterPos, hLumFilterSize,

                            c->srcFormat, formatConvBuffer,

                            pal, 0);

            if (CONFIG_SWSCALE_ALPHA && alpPixBuf)

                RENAME(hyscale)(c, alpPixBuf[ lumBufIndex ], dstW, src2, srcW, lumXInc,

                                flags, hLumFilter, hLumFilterPos, hLumFilterSize,

                                c->srcFormat, formatConvBuffer,

                                pal, 1);

            lastInLumBuf++;

        }

        while(lastInChrBuf < lastChrSrcY) {

            uint8_t *src1= src[1]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[1];

            uint8_t *src2= src[2]+(lastInChrBuf + 1 - chrSrcSliceY)*srcStride[2];

            chrBufIndex++;

            DEBUG_BUFFERS("\t\tchrBufIndex %d: lastInChrBuf: %d\n",

                               chrBufIndex,    lastInChrBuf);

            assert(chrBufIndex < 2*vChrBufSize);

            assert(lastInChrBuf + 1 - chrSrcSliceY < (chrSrcSliceH));

            assert(lastInChrBuf + 1 - chrSrcSliceY >= 0);

            //FIXME replace parameters through context struct (some at least)

            if (!(isGray(srcFormat) || isGray(dstFormat)))

                RENAME(hcscale)(c, chrPixBuf[ chrBufIndex ], chrDstW, src1, src2, chrSrcW, chrXInc,

                                flags, hChrFilter, hChrFilterPos, hChrFilterSize,

                                c->srcFormat, formatConvBuffer,

                                pal);

            lastInChrBuf++;

        }

        //wrap buf index around to stay inside the ring buffer

        if (lumBufIndex >= vLumBufSize) lumBufIndex-= vLumBufSize;

        if (chrBufIndex >= vChrBufSize) chrBufIndex-= vChrBufSize;

        if (!enough_lines)

            break; //we can't output a dstY line so let's try with the next slice

#if COMPILE_TEMPLATE_MMX

        c->blueDither= ff_dither8[dstY&1];

        if (c->dstFormat == PIX_FMT_RGB555 || c->dstFormat == PIX_FMT_BGR555)

            c->greenDither= ff_dither8[dstY&1];

        else

            c->greenDither= ff_dither4[dstY&1];

        c->redDither= ff_dither8[(dstY+1)&1];

#endif

        if (dstY < dstH-2) {

            const int16_t **lumSrcPtr= (const int16_t **) lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;

            const int16_t **chrSrcPtr= (const int16_t **) chrPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;

            const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **) alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;

#if COMPILE_TEMPLATE_MMX

            int i;

            if (flags & SWS_ACCURATE_RND) {

                int s= APCK_SIZE / 8;

                for (i=0; i<vLumFilterSize; i+=2) {

                    *(void**)&lumMmxFilter[s*i              ]= lumSrcPtr[i  ];

                    *(void**)&lumMmxFilter[s*i+APCK_PTR2/4  ]= lumSrcPtr[i+(vLumFilterSize>1)];

                              lumMmxFilter[s*i+APCK_COEF/4  ]=

                              lumMmxFilter[s*i+APCK_COEF/4+1]= vLumFilter[dstY*vLumFilterSize + i    ]

                        + (vLumFilterSize>1 ? vLumFilter[dstY*vLumFilterSize + i + 1]<<16 : 0);

                    if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {

                        *(void**)&alpMmxFilter[s*i              ]= alpSrcPtr[i  ];

                        *(void**)&alpMmxFilter[s*i+APCK_PTR2/4  ]= alpSrcPtr[i+(vLumFilterSize>1)];

                                  alpMmxFilter[s*i+APCK_COEF/4  ]=

                                  alpMmxFilter[s*i+APCK_COEF/4+1]= lumMmxFilter[s*i+APCK_COEF/4  ];

                    }

                }

                for (i=0; i<vChrFilterSize; i+=2) {

                    *(void**)&chrMmxFilter[s*i              ]= chrSrcPtr[i  ];

                    *(void**)&chrMmxFilter[s*i+APCK_PTR2/4  ]= chrSrcPtr[i+(vChrFilterSize>1)];

                              chrMmxFilter[s*i+APCK_COEF/4  ]=

                              chrMmxFilter[s*i+APCK_COEF/4+1]= vChrFilter[chrDstY*vChrFilterSize + i    ]

                        + (vChrFilterSize>1 ? vChrFilter[chrDstY*vChrFilterSize + i + 1]<<16 : 0);

                }

            } else {

                for (i=0; i<vLumFilterSize; i++) {

                    lumMmxFilter[4*i+0]= (int32_t)lumSrcPtr[i];

                    lumMmxFilter[4*i+1]= (uint64_t)lumSrcPtr[i] >> 32;

                    lumMmxFilter[4*i+2]=

                    lumMmxFilter[4*i+3]=

                        ((uint16_t)vLumFilter[dstY*vLumFilterSize + i])*0x10001;

                    if (CONFIG_SWSCALE_ALPHA && alpPixBuf) {

                        alpMmxFilter[4*i+0]= (int32_t)alpSrcPtr[i];

                        alpMmxFilter[4*i+1]= (uint64_t)alpSrcPtr[i] >> 32;

                        alpMmxFilter[4*i+2]=

                        alpMmxFilter[4*i+3]= lumMmxFilter[4*i+2];

                    }

                }

                for (i=0; i<vChrFilterSize; i++) {

                    chrMmxFilter[4*i+0]= (int32_t)chrSrcPtr[i];

                    chrMmxFilter[4*i+1]= (uint64_t)chrSrcPtr[i] >> 32;

                    chrMmxFilter[4*i+2]=

                    chrMmxFilter[4*i+3]=

                        ((uint16_t)vChrFilter[chrDstY*vChrFilterSize + i])*0x10001;

                }

            }

#endif

            if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {

                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;

                if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi

                c->yuv2nv12X(c,

                             vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                             vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                             dest, uDest, dstW, chrDstW, dstFormat);

            } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12 like

                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;

                if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi

                if (is16BPS(dstFormat)) {

                    yuv2yuvX16inC(

                                  vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                  vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                  alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest, (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,

                                  dstFormat);

                } else if (vLumFilterSize == 1 && vChrFilterSize == 1) { // unscaled YV12

                    int16_t *lumBuf = lumSrcPtr[0];

                    int16_t *chrBuf= chrSrcPtr[0];

                    int16_t *alpBuf= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? alpSrcPtr[0] : NULL;

                    c->yuv2yuv1(c, lumBuf, chrBuf, alpBuf, dest, uDest, vDest, aDest, dstW, chrDstW);

                } else { //General YV12

                    c->yuv2yuvX(c,

                                vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                alpSrcPtr, dest, uDest, vDest, aDest, dstW, chrDstW);

                }

            } else {

                assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);

                assert(chrSrcPtr + vChrFilterSize - 1 < chrPixBuf + vChrBufSize*2);

                if (vLumFilterSize == 1 && vChrFilterSize == 2) { //unscaled RGB

                    int chrAlpha= vChrFilter[2*dstY+1];

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c, //FIXME write a packed1_full function

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

                        c->yuv2packed1(c, *lumSrcPtr, *chrSrcPtr, *(chrSrcPtr+1),

                                       alpPixBuf ? *alpSrcPtr : NULL,

                                       dest, dstW, chrAlpha, dstFormat, flags, dstY);

                    }

                } else if (vLumFilterSize == 2 && vChrFilterSize == 2) { //bilinear upscale RGB

                    int lumAlpha= vLumFilter[2*dstY+1];

                    int chrAlpha= vChrFilter[2*dstY+1];

                    lumMmxFilter[2]=

                    lumMmxFilter[3]= vLumFilter[2*dstY   ]*0x10001;

                    chrMmxFilter[2]=

                    chrMmxFilter[3]= vChrFilter[2*chrDstY]*0x10001;

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c, //FIXME write a packed2_full function

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

                        c->yuv2packed2(c, *lumSrcPtr, *(lumSrcPtr+1), *chrSrcPtr, *(chrSrcPtr+1),

                                       alpPixBuf ? *alpSrcPtr : NULL, alpPixBuf ? *(alpSrcPtr+1) : NULL,

                                       dest, dstW, lumAlpha, chrAlpha, dstY);

                    }

                } else { //general RGB

                    if(flags & SWS_FULL_CHR_H_INT) {

                        yuv2rgbXinC_full(c,

                                         vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                         vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                         alpSrcPtr, dest, dstW, dstY);

                    } else {

                        c->yuv2packedX(c,

                                       vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                       vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                       alpSrcPtr, dest, dstW, dstY);

                    }

                }

            }

        } else { // hmm looks like we can't use MMX here without overwriting this array's tail

            const int16_t **lumSrcPtr= (const int16_t **)lumPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize;

            const int16_t **chrSrcPtr= (const int16_t **)chrPixBuf + chrBufIndex + firstChrSrcY - lastInChrBuf + vChrBufSize;

            const int16_t **alpSrcPtr= (CONFIG_SWSCALE_ALPHA && alpPixBuf) ? (const int16_t **)alpPixBuf + lumBufIndex + firstLumSrcY - lastInLumBuf + vLumBufSize : NULL;

            if (dstFormat == PIX_FMT_NV12 || dstFormat == PIX_FMT_NV21) {

                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;

                if (dstY&chrSkipMask) uDest= NULL; //FIXME split functions in lumi / chromi

                yuv2nv12XinC(

                             vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                             vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                             dest, uDest, dstW, chrDstW, dstFormat);

            } else if (isPlanarYUV(dstFormat) || dstFormat==PIX_FMT_GRAY8) { //YV12

                const int chrSkipMask= (1<<c->chrDstVSubSample)-1;

                if ((dstY&chrSkipMask) || isGray(dstFormat)) uDest=vDest= NULL; //FIXME split functions in lumi / chromi

                if (is16BPS(dstFormat)) {

                    yuv2yuvX16inC(

                                  vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                  vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                  alpSrcPtr, (uint16_t *) dest, (uint16_t *) uDest, (uint16_t *) vDest, (uint16_t *) aDest, dstW, chrDstW,

                                  dstFormat);

                } else {

                    yuv2yuvXinC(

                                vLumFilter+dstY*vLumFilterSize   , lumSrcPtr, vLumFilterSize,

                                vChrFilter+chrDstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                alpSrcPtr, dest, uDest, vDest, aDest, dstW, chrDstW);

                }

            } else {

                assert(lumSrcPtr + vLumFilterSize - 1 < lumPixBuf + vLumBufSize*2);

                assert(chrSrcPtr + vChrFilterSize - 1 < chrPixBuf + vChrBufSize*2);

                if(flags & SWS_FULL_CHR_H_INT) {

                    yuv2rgbXinC_full(c,

                                     vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                     vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                     alpSrcPtr, dest, dstW, dstY);

                } else {

                    yuv2packedXinC(c,

                                   vLumFilter+dstY*vLumFilterSize, lumSrcPtr, vLumFilterSize,

                                   vChrFilter+dstY*vChrFilterSize, chrSrcPtr, vChrFilterSize,

                                   alpSrcPtr, dest, dstW, dstY);

                }

            }

        }

    }

    if ((dstFormat == PIX_FMT_YUVA420P) && !alpPixBuf)

        fillPlane(dst[3], dstStride[3], dstW, dstY-lastDstY, lastDstY, 255);

#if COMPILE_TEMPLATE_MMX

    if (flags & SWS_CPU_CAPS_MMX2 )  __asm__ volatile("sfence":::"memory");

    /* On K6 femms is faster than emms. On K7 femms is directly mapped to emms. */

    if (flags & SWS_CPU_CAPS_3DNOW)  __asm__ volatile("femms" :::"memory");

    else                             __asm__ volatile("emms"  :::"memory");

#endif

    /* store changed local vars back in the context */

    c->dstY= dstY;

    c->lumBufIndex= lumBufIndex;

    c->chrBufIndex= chrBufIndex;

    c->lastInLumBuf= lastInLumBuf;

    c->lastInChrBuf= lastInChrBuf;

    return dstY - lastDstY;

}


static uint32_t bonito_spciconf_readb(void *opaque, target_phys_addr_t addr)

{

    PCIBonitoState *s = opaque;

    uint32_t pciaddr;

    uint16_t status;

    DPRINTF("bonito_spciconf_readb "TARGET_FMT_plx"  \n", addr);

    pciaddr = bonito_sbridge_pciaddr(s, addr);

    if (pciaddr == 0xffffffff) {

        return 0xff;

    }

    /* set the pci address in s->config_reg */

    s->pcihost->config_reg = (pciaddr) | (1u << 31);

    /* clear PCI_STATUS_REC_MASTER_ABORT and PCI_STATUS_REC_TARGET_ABORT */

    status = pci_get_word(s->dev.config + PCI_STATUS);

    status &= ~(PCI_STATUS_REC_MASTER_ABORT | PCI_STATUS_REC_TARGET_ABORT);

    pci_set_word(s->dev.config + PCI_STATUS, status);

    return pci_data_read(s->pcihost->bus, s->pcihost->config_reg, 1);

}


static void qdev_get_legacy_property(DeviceState *dev, Visitor *v, void *opaque,

                                     const char *name, Error **errp)

{

    Property *prop = opaque;

    if (prop->info->print) {

        char buffer[1024];

        char *ptr = buffer;

        prop->info->print(dev, prop, buffer, sizeof(buffer));

        visit_type_str(v, &ptr, name, errp);

    } else {

        error_set(errp, QERR_PERMISSION_DENIED);

    }

}


static char *value_string(char *buf, int buf_size, struct unit_value uv)

{

    double vald;

    int show_float = 0;

    if (uv.unit == unit_second_str) {

        vald = uv.val.d;

        show_float = 1;

    } else {

        vald = uv.val.i;

    }

    if (uv.unit == unit_second_str && use_value_sexagesimal_format) {

        double secs;

        int hours, mins;

        secs  = vald;

        mins  = (int)secs / 60;

        secs  = secs - mins * 60;

        hours = mins / 60;

        mins %= 60;

        snprintf(buf, buf_size, "%d:%02d:%09.6f", hours, mins, secs);

    } else {

        const char *prefix_string = "";

        int l;

        if (use_value_prefix && vald > 1) {

            long long int index;

            if (uv.unit == unit_byte_str && use_byte_value_binary_prefix) {

                index = (long long int) (log2(vald)) / 10;

                index = av_clip(index, 0, FF_ARRAY_ELEMS(binary_unit_prefixes) - 1);

                vald /= exp2(index * 10);

                prefix_string = binary_unit_prefixes[index];

            } else {

                index = (long long int) (log10(vald)) / 3;

                index = av_clip(index, 0, FF_ARRAY_ELEMS(decimal_unit_prefixes) - 1);

                vald /= pow(10, index * 3);

                prefix_string = decimal_unit_prefixes[index];

            }

        }

        if (show_float || (use_value_prefix && vald != (long long int)vald))

            l = snprintf(buf, buf_size, "%f", vald);

        else

            l = snprintf(buf, buf_size, "%lld", (long long int)vald);

        snprintf(buf+l, buf_size-l, "%s%s%s", *prefix_string || show_value_unit ? " " : "",

                 prefix_string, show_value_unit ? uv.unit : "");

    }

    return buf;

}


static int mjpeg_decode_dht(MJpegDecodeContext *s)

{

    int len, index, i, class, n, v, code_max;

    uint8_t bits_table[17];

    uint8_t val_table[256];

    len = get_bits(&s->gb, 16) - 2;

    while (len > 0) {

        if (len < 17)

            return -1;

        class = get_bits(&s->gb, 4);

        if (class >= 2)

            return -1;

        index = get_bits(&s->gb, 4);

        if (index >= 4)

            return -1;

        n = 0;

        for(i=1;i<=16;i++) {

            bits_table[i] = get_bits(&s->gb, 8);

            n += bits_table[i];

        }

        len -= 17;

        if (len < n || n > 256)

            return -1;

        code_max = 0;

        for(i=0;i<n;i++) {

            v = get_bits(&s->gb, 8);

            if (v > code_max)

                code_max = v;

            val_table[i] = v;

        }

        len -= n;

        /* build VLC and flush previous vlc if present */

        free_vlc(&s->vlcs[class][index]);

        dprintf("class=%d index=%d nb_codes=%d\n",

               class, index, code_max + 1);

        if(build_vlc(&s->vlcs[class][index], bits_table, val_table, code_max + 1) < 0){

            return -1;

        }

    }

    return 0;

}