static int wc3_read_header(AVFormatContext *s,
                           AVFormatParameters *ap)
{
    Wc3DemuxContext *wc3 = s->priv_data;
    ByteIOContext *pb = s->pb;
    unsigned int fourcc_tag;
    unsigned int size;
    AVStream *st;
    unsigned char preamble[WC3_PREAMBLE_SIZE];
    int ret = 0;
    int current_palette = 0;
    int bytes_to_read;
    int i;
    unsigned char rotate;
    wc3->width = WC3_DEFAULT_WIDTH;
    wc3->height = WC3_DEFAULT_HEIGHT;
    wc3->palettes = NULL;
    wc3->palette_count = 0;
    wc3->pts = 0;
    wc3->video_stream_index = wc3->audio_stream_index = 0;
    url_fseek(pb, 12, SEEK_CUR);
    if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
        WC3_PREAMBLE_SIZE)
        return AVERROR(EIO);
    fourcc_tag = AV_RL32(&preamble[0]);
    size = (AV_RB32(&preamble[4]) + 1) & (~1);
    do {
        switch (fourcc_tag) {
        case SOND_TAG:
        case INDX_TAG:
            url_fseek(pb, size, SEEK_CUR);
            break;
        case PC__TAG:
            url_fseek(pb, 8, SEEK_CUR);
            if ((ret = get_buffer(pb, preamble, 4)) != 4)
                return AVERROR(EIO);
            wc3->palette_count = AV_RL32(&preamble[0]);
            if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){
                wc3->palette_count= 0;
                return -1;
            }
            wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);
            break;
        case BNAM_TAG:
            if ((unsigned)size < 512)
                bytes_to_read = size;
            else
                bytes_to_read = 512;
            if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)
                return AVERROR(EIO);
            break;
        case SIZE_TAG:
            if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
                WC3_PREAMBLE_SIZE)
                return AVERROR(EIO);
            wc3->width = AV_RL32(&preamble[0]);
            wc3->height = AV_RL32(&preamble[4]);
            break;
        case PALT_TAG:
            if ((unsigned)current_palette >= wc3->palette_count)
                return AVERROR_INVALIDDATA;
            if ((ret = get_buffer(pb,
                &wc3->palettes[current_palette * PALETTE_SIZE],
                PALETTE_SIZE)) != PALETTE_SIZE)
                return AVERROR(EIO);
            for (i = current_palette * PALETTE_SIZE;
                 i < (current_palette + 1) * PALETTE_SIZE; i++) {
                rotate = ((wc3->palettes[i] << 2) & 0xFF) |
                         ((wc3->palettes[i] >> 6) & 0xFF);
                wc3->palettes[i] = wc3_pal_lookup[rotate];
            }
            current_palette++;
            break;
        default:
            av_log(s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\n",
                preamble[0], preamble[1], preamble[2], preamble[3],
                preamble[0], preamble[1], preamble[2], preamble[3]);
            return AVERROR_INVALIDDATA;
            break;
        }
        if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=
            WC3_PREAMBLE_SIZE)
            return AVERROR(EIO);
        fourcc_tag = AV_RL32(&preamble[0]);
        size = (AV_RB32(&preamble[4]) + 1) & (~1);
    } while (fourcc_tag != BRCH_TAG);
    st = av_new_stream(s, 0);
    if (!st)
        return AVERROR(ENOMEM);
    av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
    wc3->video_stream_index = st->index;
    st->codec->codec_type = CODEC_TYPE_VIDEO;
    st->codec->codec_id = CODEC_ID_XAN_WC3;
    st->codec->codec_tag = 0;
    st->codec->width = wc3->width;
    st->codec->height = wc3->height;
    st->codec->palctrl = &wc3->palette_control;
    st = av_new_stream(s, 0);
    if (!st)
        return AVERROR(ENOMEM);
    av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);
    wc3->audio_stream_index = st->index;
    st->codec->codec_type = CODEC_TYPE_AUDIO;
    st->codec->codec_id = CODEC_ID_PCM_S16LE;
    st->codec->codec_tag = 1;
    st->codec->channels = WC3_AUDIO_CHANNELS;
    st->codec->bits_per_sample = WC3_AUDIO_BITS;
    st->codec->sample_rate = WC3_SAMPLE_RATE;
    st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *
        st->codec->bits_per_sample;
    st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;
    return 0;
}
['static int wc3_read_header(AVFormatContext *s,\n                           AVFormatParameters *ap)\n{\n    Wc3DemuxContext *wc3 = s->priv_data;\n    ByteIOContext *pb = s->pb;\n    unsigned int fourcc_tag;\n    unsigned int size;\n    AVStream *st;\n    unsigned char preamble[WC3_PREAMBLE_SIZE];\n    int ret = 0;\n    int current_palette = 0;\n    int bytes_to_read;\n    int i;\n    unsigned char rotate;\n    wc3->width = WC3_DEFAULT_WIDTH;\n    wc3->height = WC3_DEFAULT_HEIGHT;\n    wc3->palettes = NULL;\n    wc3->palette_count = 0;\n    wc3->pts = 0;\n    wc3->video_stream_index = wc3->audio_stream_index = 0;\n    url_fseek(pb, 12, SEEK_CUR);\n    if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=\n        WC3_PREAMBLE_SIZE)\n        return AVERROR(EIO);\n    fourcc_tag = AV_RL32(&preamble[0]);\n    size = (AV_RB32(&preamble[4]) + 1) & (~1);\n    do {\n        switch (fourcc_tag) {\n        case SOND_TAG:\n        case INDX_TAG:\n            url_fseek(pb, size, SEEK_CUR);\n            break;\n        case PC__TAG:\n            url_fseek(pb, 8, SEEK_CUR);\n            if ((ret = get_buffer(pb, preamble, 4)) != 4)\n                return AVERROR(EIO);\n            wc3->palette_count = AV_RL32(&preamble[0]);\n            if((unsigned)wc3->palette_count >= UINT_MAX / PALETTE_SIZE){\n                wc3->palette_count= 0;\n                return -1;\n            }\n            wc3->palettes = av_malloc(wc3->palette_count * PALETTE_SIZE);\n            break;\n        case BNAM_TAG:\n            if ((unsigned)size < 512)\n                bytes_to_read = size;\n            else\n                bytes_to_read = 512;\n            if ((ret = get_buffer(pb, s->title, bytes_to_read)) != bytes_to_read)\n                return AVERROR(EIO);\n            break;\n        case SIZE_TAG:\n            if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=\n                WC3_PREAMBLE_SIZE)\n                return AVERROR(EIO);\n            wc3->width = AV_RL32(&preamble[0]);\n            wc3->height = AV_RL32(&preamble[4]);\n            break;\n        case PALT_TAG:\n            if ((unsigned)current_palette >= wc3->palette_count)\n                return AVERROR_INVALIDDATA;\n            if ((ret = get_buffer(pb,\n                &wc3->palettes[current_palette * PALETTE_SIZE],\n                PALETTE_SIZE)) != PALETTE_SIZE)\n                return AVERROR(EIO);\n            for (i = current_palette * PALETTE_SIZE;\n                 i < (current_palette + 1) * PALETTE_SIZE; i++) {\n                rotate = ((wc3->palettes[i] << 2) & 0xFF) |\n                         ((wc3->palettes[i] >> 6) & 0xFF);\n                wc3->palettes[i] = wc3_pal_lookup[rotate];\n            }\n            current_palette++;\n            break;\n        default:\n            av_log(s, AV_LOG_ERROR, "  unrecognized WC3 chunk: %c%c%c%c (0x%02X%02X%02X%02X)\\n",\n                preamble[0], preamble[1], preamble[2], preamble[3],\n                preamble[0], preamble[1], preamble[2], preamble[3]);\n            return AVERROR_INVALIDDATA;\n            break;\n        }\n        if ((ret = get_buffer(pb, preamble, WC3_PREAMBLE_SIZE)) !=\n            WC3_PREAMBLE_SIZE)\n            return AVERROR(EIO);\n        fourcc_tag = AV_RL32(&preamble[0]);\n        size = (AV_RB32(&preamble[4]) + 1) & (~1);\n    } while (fourcc_tag != BRCH_TAG);\n    st = av_new_stream(s, 0);\n    if (!st)\n        return AVERROR(ENOMEM);\n    av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);\n    wc3->video_stream_index = st->index;\n    st->codec->codec_type = CODEC_TYPE_VIDEO;\n    st->codec->codec_id = CODEC_ID_XAN_WC3;\n    st->codec->codec_tag = 0;\n    st->codec->width = wc3->width;\n    st->codec->height = wc3->height;\n    st->codec->palctrl = &wc3->palette_control;\n    st = av_new_stream(s, 0);\n    if (!st)\n        return AVERROR(ENOMEM);\n    av_set_pts_info(st, 33, 1, WC3_FRAME_FPS);\n    wc3->audio_stream_index = st->index;\n    st->codec->codec_type = CODEC_TYPE_AUDIO;\n    st->codec->codec_id = CODEC_ID_PCM_S16LE;\n    st->codec->codec_tag = 1;\n    st->codec->channels = WC3_AUDIO_CHANNELS;\n    st->codec->bits_per_sample = WC3_AUDIO_BITS;\n    st->codec->sample_rate = WC3_SAMPLE_RATE;\n    st->codec->bit_rate = st->codec->channels * st->codec->sample_rate *\n        st->codec->bits_per_sample;\n    st->codec->block_align = WC3_AUDIO_BITS * WC3_AUDIO_CHANNELS;\n    return 0;\n}']