static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx,

                                const uint8_t *buf, int buf_size)

{

    const uint8_t   *buf_ptr = buf, *bs_hdr;

    uint32_t        frame_num, word2, check_sum, data_size;

    uint32_t        y_offset, u_offset, v_offset, starts[3], ends[3];

    uint16_t        height, width;

    int             i, j;



    /* parse and check the OS header */

    frame_num = bytestream_get_le32(&buf_ptr);

    word2     = bytestream_get_le32(&buf_ptr);

    check_sum = bytestream_get_le32(&buf_ptr);

    data_size = bytestream_get_le32(&buf_ptr);



    if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) {

        av_log(avctx, AV_LOG_ERROR, "OS header checksum mismatch!\n");

        return AVERROR_INVALIDDATA;

    }



    /* parse the bitstream header */

    bs_hdr = buf_ptr;



    if (bytestream_get_le16(&buf_ptr) != 32) {

        av_log(avctx, AV_LOG_ERROR, "Unsupported codec version!\n");

        return AVERROR_INVALIDDATA;

    }



    ctx->frame_num   =  frame_num;

    ctx->frame_flags =  bytestream_get_le16(&buf_ptr);

    ctx->data_size   = (bytestream_get_le32(&buf_ptr) + 7) >> 3;

    ctx->cb_offset   = *buf_ptr++;



    if (ctx->data_size == 16)

        return 4;

    if (ctx->data_size > buf_size)

        ctx->data_size = buf_size;



    buf_ptr += 3; // skip reserved byte and checksum



    /* check frame dimensions */

    height = bytestream_get_le16(&buf_ptr);

    width  = bytestream_get_le16(&buf_ptr);

    if (av_image_check_size(width, height, 0, avctx))

        return AVERROR_INVALIDDATA;



    if (width != ctx->width || height != ctx->height) {

        av_dlog(avctx, "Frame dimensions changed!\n");



        ctx->width  = width;

        ctx->height = height;



        free_frame_buffers(ctx);

        allocate_frame_buffers(ctx, avctx);

        avcodec_set_dimensions(avctx, width, height);

    }



    y_offset = bytestream_get_le32(&buf_ptr);

    v_offset = bytestream_get_le32(&buf_ptr);

    u_offset = bytestream_get_le32(&buf_ptr);



    /* unfortunately there is no common order of planes in the buffer */

    /* so we use that sorting algo for determining planes data sizes  */

    starts[0] = y_offset;

    starts[1] = v_offset;

    starts[2] = u_offset;



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

        ends[j] = ctx->data_size;

        for (i = 2; i >= 0; i--)

            if (starts[i] < ends[j] && starts[i] > starts[j])

                ends[j] = starts[i];

    }



    ctx->y_data_size = ends[0] - starts[0];

    ctx->v_data_size = ends[1] - starts[1];

    ctx->u_data_size = ends[2] - starts[2];

    if (FFMAX3(y_offset, v_offset, u_offset) >= ctx->data_size - 16 ||

        FFMIN3(ctx->y_data_size, ctx->v_data_size, ctx->u_data_size) <= 0) {

        av_log(avctx, AV_LOG_ERROR, "One of the y/u/v offsets is invalid\n");

        return AVERROR_INVALIDDATA;

    }



    ctx->y_data_ptr = bs_hdr + y_offset;

    ctx->v_data_ptr = bs_hdr + v_offset;

    ctx->u_data_ptr = bs_hdr + u_offset;

    ctx->alt_quant  = buf_ptr + sizeof(uint32_t);



    if (ctx->data_size == 16) {

        av_log(avctx, AV_LOG_DEBUG, "Sync frame encountered!\n");

        return 16;

    }



    if (ctx->frame_flags & BS_8BIT_PEL) {

        av_log_ask_for_sample(avctx, "8-bit pixel format\n");

        return AVERROR_PATCHWELCOME;

    }



    if (ctx->frame_flags & BS_MV_X_HALF || ctx->frame_flags & BS_MV_Y_HALF) {

        av_log_ask_for_sample(avctx, "halfpel motion vectors\n");

        return AVERROR_PATCHWELCOME;

    }



    return 0;

}

static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx,

                                const uint8_t *buf, int buf_size)

{

    const uint8_t   *buf_ptr = buf, *bs_hdr;

    uint32_t        frame_num, word2, check_sum, data_size;

    uint32_t        y_offset, u_offset, v_offset, starts[3], ends[3];

    uint16_t        height, width;

    int             i, j;



    

    frame_num = bytestream_get_le32(&buf_ptr);

    word2     = bytestream_get_le32(&buf_ptr);

    check_sum = bytestream_get_le32(&buf_ptr);

    data_size = bytestream_get_le32(&buf_ptr);



    if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) {

        av_log(avctx, AV_LOG_ERROR, "OS header checksum mismatch!\n");

        return AVERROR_INVALIDDATA;

    }



    

    bs_hdr = buf_ptr;



    if (bytestream_get_le16(&buf_ptr) != 32) {

        av_log(avctx, AV_LOG_ERROR, "Unsupported codec version!\n");

        return AVERROR_INVALIDDATA;

    }



    ctx->frame_num   =  frame_num;

    ctx->frame_flags =  bytestream_get_le16(&buf_ptr);

    ctx->data_size   = (bytestream_get_le32(&buf_ptr) + 7) >> 3;

    ctx->cb_offset   = *buf_ptr++;



    if (ctx->data_size == 16)

        return 4;

    if (ctx->data_size > buf_size)

        ctx->data_size = buf_size;



    buf_ptr += 3; 



    

    height = bytestream_get_le16(&buf_ptr);

    width  = bytestream_get_le16(&buf_ptr);

    if (av_image_check_size(width, height, 0, avctx))

        return AVERROR_INVALIDDATA;



    if (width != ctx->width || height != ctx->height) {

        av_dlog(avctx, "Frame dimensions changed!\n");



        ctx->width  = width;

        ctx->height = height;



        free_frame_buffers(ctx);

        allocate_frame_buffers(ctx, avctx);

        avcodec_set_dimensions(avctx, width, height);

    }



    y_offset = bytestream_get_le32(&buf_ptr);

    v_offset = bytestream_get_le32(&buf_ptr);

    u_offset = bytestream_get_le32(&buf_ptr);



    

    

    starts[0] = y_offset;

    starts[1] = v_offset;

    starts[2] = u_offset;



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

        ends[j] = ctx->data_size;

        for (i = 2; i >= 0; i--)

            if (starts[i] < ends[j] && starts[i] > starts[j])

                ends[j] = starts[i];

    }



    ctx->y_data_size = ends[0] - starts[0];

    ctx->v_data_size = ends[1] - starts[1];

    ctx->u_data_size = ends[2] - starts[2];

    if (FFMAX3(y_offset, v_offset, u_offset) >= ctx->data_size - 16 ||

        FFMIN3(ctx->y_data_size, ctx->v_data_size, ctx->u_data_size) <= 0) {

        av_log(avctx, AV_LOG_ERROR, "One of the y/u/v offsets is invalid\n");

        return AVERROR_INVALIDDATA;

    }



    ctx->y_data_ptr = bs_hdr + y_offset;

    ctx->v_data_ptr = bs_hdr + v_offset;

    ctx->u_data_ptr = bs_hdr + u_offset;

    ctx->alt_quant  = buf_ptr + sizeof(uint32_t);



    if (ctx->data_size == 16) {

        av_log(avctx, AV_LOG_DEBUG, "Sync frame encountered!\n");

        return 16;

    }



    if (ctx->frame_flags & BS_8BIT_PEL) {

        av_log_ask_for_sample(avctx, "8-bit pixel format\n");

        return AVERROR_PATCHWELCOME;

    }



    if (ctx->frame_flags & BS_MV_X_HALF || ctx->frame_flags & BS_MV_Y_HALF) {

        av_log_ask_for_sample(avctx, "halfpel motion vectors\n");

        return AVERROR_PATCHWELCOME;

    }



    return 0;

}

static int FUNC_0(Indeo3DecodeContext *VAR_0, AVCodecContext *VAR_1,

                                const uint8_t *VAR_2, int VAR_3)

{

    const uint8_t   *VAR_4 = VAR_2, *bs_hdr;

    uint32_t        frame_num, word2, check_sum, data_size;

    uint32_t        y_offset, u_offset, v_offset, starts[3], ends[3];

    uint16_t        height, width;

    int             VAR_5, VAR_6;



    

    frame_num = bytestream_get_le32(&VAR_4);

    word2     = bytestream_get_le32(&VAR_4);

    check_sum = bytestream_get_le32(&VAR_4);

    data_size = bytestream_get_le32(&VAR_4);



    if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) {

        av_log(VAR_1, AV_LOG_ERROR, "OS header checksum mismatch!\n");

        return AVERROR_INVALIDDATA;

    }



    

    bs_hdr = VAR_4;



    if (bytestream_get_le16(&VAR_4) != 32) {

        av_log(VAR_1, AV_LOG_ERROR, "Unsupported codec version!\n");

        return AVERROR_INVALIDDATA;

    }



    VAR_0->frame_num   =  frame_num;

    VAR_0->frame_flags =  bytestream_get_le16(&VAR_4);

    VAR_0->data_size   = (bytestream_get_le32(&VAR_4) + 7) >> 3;

    VAR_0->cb_offset   = *VAR_4++;



    if (VAR_0->data_size == 16)

        return 4;

    if (VAR_0->data_size > VAR_3)

        VAR_0->data_size = VAR_3;



    VAR_4 += 3; 



    

    height = bytestream_get_le16(&VAR_4);

    width  = bytestream_get_le16(&VAR_4);

    if (av_image_check_size(width, height, 0, VAR_1))

        return AVERROR_INVALIDDATA;



    if (width != VAR_0->width || height != VAR_0->height) {

        av_dlog(VAR_1, "Frame dimensions changed!\n");



        VAR_0->width  = width;

        VAR_0->height = height;



        free_frame_buffers(VAR_0);

        allocate_frame_buffers(VAR_0, VAR_1);

        avcodec_set_dimensions(VAR_1, width, height);

    }



    y_offset = bytestream_get_le32(&VAR_4);

    v_offset = bytestream_get_le32(&VAR_4);

    u_offset = bytestream_get_le32(&VAR_4);



    

    

    starts[0] = y_offset;

    starts[1] = v_offset;

    starts[2] = u_offset;



    for (VAR_6 = 0; VAR_6 < 3; VAR_6++) {

        ends[VAR_6] = VAR_0->data_size;

        for (VAR_5 = 2; VAR_5 >= 0; VAR_5--)

            if (starts[VAR_5] < ends[VAR_6] && starts[VAR_5] > starts[VAR_6])

                ends[VAR_6] = starts[VAR_5];

    }



    VAR_0->y_data_size = ends[0] - starts[0];

    VAR_0->v_data_size = ends[1] - starts[1];

    VAR_0->u_data_size = ends[2] - starts[2];

    if (FFMAX3(y_offset, v_offset, u_offset) >= VAR_0->data_size - 16 ||

        FFMIN3(VAR_0->y_data_size, VAR_0->v_data_size, VAR_0->u_data_size) <= 0) {

        av_log(VAR_1, AV_LOG_ERROR, "One of the y/u/v offsets is invalid\n");

        return AVERROR_INVALIDDATA;

    }



    VAR_0->y_data_ptr = bs_hdr + y_offset;

    VAR_0->v_data_ptr = bs_hdr + v_offset;

    VAR_0->u_data_ptr = bs_hdr + u_offset;

    VAR_0->alt_quant  = VAR_4 + sizeof(uint32_t);



    if (VAR_0->data_size == 16) {

        av_log(VAR_1, AV_LOG_DEBUG, "Sync frame encountered!\n");

        return 16;

    }



    if (VAR_0->frame_flags & BS_8BIT_PEL) {

        av_log_ask_for_sample(VAR_1, "8-bit pixel format\n");

        return AVERROR_PATCHWELCOME;

    }



    if (VAR_0->frame_flags & BS_MV_X_HALF || VAR_0->frame_flags & BS_MV_Y_HALF) {

        av_log_ask_for_sample(VAR_1, "halfpel motion vectors\n");

        return AVERROR_PATCHWELCOME;

    }



    return 0;

}

static int FUNC_0(Indeo3DecodeContext *VAR_0, AVCodecContext *VAR_1,
const uint8_t *VAR_2, int VAR_3)
{ const uint8_t   *VAR_4 = VAR_2, *bs_hdr; uint32_t        frame_num, word2, check_sum, data_size; uint32_t        y_offset, u_offset, v_offset, starts[3], ends[3]; uint16_t        height, width; int             VAR_5, VAR_6; frame_num = bytestream_get_le32(&VAR_4); word2     = bytestream_get_le32(&VAR_4); check_sum = bytestream_get_le32(&VAR_4); data_size = bytestream_get_le32(&VAR_4); if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) { av_log(VAR_1, AV_LOG_ERROR, "OS header checksum mismatch!\n"); return AVERROR_INVALIDDATA; } bs_hdr = VAR_4; if (bytestream_get_le16(&VAR_4) != 32) { av_log(VAR_1, AV_LOG_ERROR, "Unsupported codec version!\n"); return AVERROR_INVALIDDATA; } VAR_0->frame_num   =  frame_num; VAR_0->frame_flags =  bytestream_get_le16(&VAR_4); VAR_0->data_size   = (bytestream_get_le32(&VAR_4) + 7) >> 3; VAR_0->cb_offset   = *VAR_4++; if (VAR_0->data_size == 16)
return 4; if (VAR_0->data_size > VAR_3)
VAR_0->data_size = VAR_3; VAR_4 += 3; height = bytestream_get_le16(&VAR_4); width  = bytestream_get_le16(&VAR_4); if (av_image_check_size(width, height, 0, VAR_1))
return AVERROR_INVALIDDATA; if (width != VAR_0->width || height != VAR_0->height) { av_dlog(VAR_1, "Frame dimensions changed!\n"); VAR_0->width  = width; VAR_0->height = height; free_frame_buffers(VAR_0); allocate_frame_buffers(VAR_0, VAR_1); avcodec_set_dimensions(VAR_1, width, height); } y_offset = bytestream_get_le32(&VAR_4); v_offset = bytestream_get_le32(&VAR_4); u_offset = bytestream_get_le32(&VAR_4); starts[0] = y_offset; starts[1] = v_offset; starts[2] = u_offset; for (VAR_6 = 0; VAR_6 < 3; VAR_6++) { ends[VAR_6] = VAR_0->data_size; for (VAR_5 = 2; VAR_5 >= 0; VAR_5--) if (starts[VAR_5] < ends[VAR_6] && starts[VAR_5] > starts[VAR_6])
ends[VAR_6] = starts[VAR_5]; } VAR_0->y_data_size = ends[0] - starts[0]; VAR_0->v_data_size = ends[1] - starts[1]; VAR_0->u_data_size = ends[2] - starts[2]; if (FFMAX3(y_offset, v_offset, u_offset) >= VAR_0->data_size - 16 ||
FFMIN3(VAR_0->y_data_size, VAR_0->v_data_size, VAR_0->u_data_size) <= 0) { av_log(VAR_1, AV_LOG_ERROR, "One of the y/u/v offsets is invalid\n"); return AVERROR_INVALIDDATA; } VAR_0->y_data_ptr = bs_hdr + y_offset; VAR_0->v_data_ptr = bs_hdr + v_offset; VAR_0->u_data_ptr = bs_hdr + u_offset; VAR_0->alt_quant  = VAR_4 + sizeof(uint32_t); if (VAR_0->data_size == 16) { av_log(VAR_1, AV_LOG_DEBUG, "Sync frame encountered!\n"); return 16; } if (VAR_0->frame_flags & BS_8BIT_PEL) { av_log_ask_for_sample(VAR_1, "8-bit pixel format\n"); return AVERROR_PATCHWELCOME; } if (VAR_0->frame_flags & BS_MV_X_HALF || VAR_0->frame_flags & BS_MV_Y_HALF) { av_log_ask_for_sample(VAR_1, "halfpel motion vectors\n"); return AVERROR_PATCHWELCOME; } return 0; }