⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smacker.c

📁 ffmpeg源码分析
💻 C
📖 第 1 页 / 共 2 页
字号:
    }    /* make the palette available on the way out */    out = buf + 1;    pal = (uint32_t*)smk->pic.data[1];    smk->pic.palette_has_changed = buf[0] & 1;    smk->pic.key_frame = !!(buf[0] & 2);    if(smk->pic.key_frame)        smk->pic.pict_type = FF_I_TYPE;    else        smk->pic.pict_type = FF_P_TYPE;    for(i = 0; i < 256; i++) {        int r, g, b;        r = *out++;        g = *out++;        b = *out++;        *pal++ = (r << 16) | (g << 8) | b;    }    last_reset(smk->mmap_tbl, smk->mmap_last);    last_reset(smk->mclr_tbl, smk->mclr_last);    last_reset(smk->full_tbl, smk->full_last);    last_reset(smk->type_tbl, smk->type_last);    init_get_bits(&gb, buf + 769, (buf_size - 769) * 8);    blk = 0;    bw = avctx->width >> 2;    bh = avctx->height >> 2;    blocks = bw * bh;    out = smk->pic.data[0];    stride = smk->pic.linesize[0];    while(blk < blocks) {        int type, run, mode;        uint16_t pix;        type = smk_get_code(&gb, smk->type_tbl, smk->type_last);        run = block_runs[(type >> 2) & 0x3F];        switch(type & 3){        case SMK_BLK_MONO:            while(run-- && blk < blocks){                int clr, map;                int hi, lo;                clr = smk_get_code(&gb, smk->mclr_tbl, smk->mclr_last);                map = smk_get_code(&gb, smk->mmap_tbl, smk->mmap_last);                out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4;                hi = clr >> 8;                lo = clr & 0xFF;                for(i = 0; i < 4; i++) {                    if(map & 1) out[0] = hi; else out[0] = lo;                    if(map & 2) out[1] = hi; else out[1] = lo;                    if(map & 4) out[2] = hi; else out[2] = lo;                    if(map & 8) out[3] = hi; else out[3] = lo;                    map >>= 4;                    out += stride;                }                blk++;            }            break;        case SMK_BLK_FULL:            mode = 0;            if(avctx->codec_tag != 0) { // In case of Smacker v4 we have three modes                if(get_bits1(&gb)) mode = 1;                else if(get_bits1(&gb)) mode = 2;            }            while(run-- && blk < blocks){                out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4;                switch(mode){                case 0:                    for(i = 0; i < 4; i++) {                        pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);                        out[2] = pix & 0xFF;                        out[3] = pix >> 8;                        pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);                        out[0] = pix & 0xFF;                        out[1] = pix >> 8;                        out += stride;                    }                    break;                case 1:                    pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);                    out[0] = out[1] = pix & 0xFF;                    out[2] = out[3] = pix >> 8;                    out += stride;                    out[0] = out[1] = pix & 0xFF;                    out[2] = out[3] = pix >> 8;                    out += stride;                    pix = smk_get_code(&gb, smk->full_tbl, smk->full_last);                    out[0] = out[1] = pix & 0xFF;                    out[2] = out[3] = pix >> 8;                    out += stride;                    out[0] = out[1] = pix & 0xFF;                    out[2] = out[3] = pix >> 8;                    out += stride;                    break;                case 2:                    for(i = 0; i < 2; i++) {                        uint16_t pix1, pix2;                        pix1 = smk_get_code(&gb, smk->full_tbl, smk->full_last);                        pix2 = smk_get_code(&gb, smk->full_tbl, smk->full_last);                        out[0] = pix1 & 0xFF; out[1] = pix1 >> 8;                        out[2] = pix2 & 0xFF; out[3] = pix2 >> 8;                        out += stride;                        out[0] = pix1 & 0xFF; out[1] = pix1 >> 8;                        out[2] = pix2 & 0xFF; out[3] = pix2 >> 8;                        out += stride;                    }                    break;                }                blk++;            }            break;        case SMK_BLK_SKIP:            while(run-- && blk < blocks)                blk++;            break;        case SMK_BLK_FILL:            mode = type >> 8;            while(run-- && blk < blocks){                uint32_t col;                out = smk->pic.data[0] + (blk / bw) * (stride * 4) + (blk % bw) * 4;                col = mode * 0x01010101;                for(i = 0; i < 4; i++) {                    *((uint32_t*)out) = col;                    out += stride;                }                blk++;            }            break;        }    }    *data_size = sizeof(AVFrame);    *(AVFrame*)data = smk->pic;    /* always report that the buffer was completely consumed */    return buf_size;}/* * * Init smacker decoder * */static int decode_init(AVCodecContext *avctx){    SmackVContext * const c = (SmackVContext *)avctx->priv_data;    c->avctx = avctx;    avctx->has_b_frames = 0;    c->pic.data[0] = NULL;    if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) {        return 1;    }    avctx->pix_fmt = PIX_FMT_PAL8;    /* decode huffman trees from extradata */    if(avctx->extradata_size < 16){        av_log(avctx, AV_LOG_ERROR, "Extradata missing!\n");        return -1;    }    decode_header_trees(c);    return 0;}/* * * Uninit smacker decoder * */static int decode_end(AVCodecContext *avctx){    SmackVContext * const smk = (SmackVContext *)avctx->priv_data;    if(smk->mmap_tbl)        av_free(smk->mmap_tbl);    if(smk->mclr_tbl)        av_free(smk->mclr_tbl);    if(smk->full_tbl)        av_free(smk->full_tbl);    if(smk->type_tbl)        av_free(smk->type_tbl);    if (smk->pic.data[0])        avctx->release_buffer(avctx, &smk->pic);    return 0;}static int smka_decode_init(AVCodecContext *avctx){    return 0;}/** * Decode Smacker audio data */static int smka_decode_frame(AVCodecContext *avctx, void *data, int *data_size, uint8_t *buf, int buf_size){    GetBitContext gb;    HuffContext h[4];    VLC vlc[4];    int16_t *samples = data;    int val;    int i, res;    int unp_size;    int bits, stereo;    int pred[2] = {0, 0};    unp_size = LE_32(buf);    init_get_bits(&gb, buf + 4, (buf_size - 4) * 8);    if(!get_bits1(&gb)){        av_log(avctx, AV_LOG_INFO, "Sound: no data\n");        *data_size = 0;        return 1;    }    stereo = get_bits1(&gb);    bits = get_bits1(&gb);    memset(vlc, 0, sizeof(VLC) * 4);    memset(h, 0, sizeof(HuffContext) * 4);    // Initialize    for(i = 0; i < (1 << (bits + stereo)); i++) {        h[i].length = 256;        h[i].maxlength = 0;        h[i].current = 0;        h[i].bits = av_mallocz(256 * 4);        h[i].lengths = av_mallocz(256 * sizeof(int));        h[i].values = av_mallocz(256 * sizeof(int));        get_bits1(&gb);        smacker_decode_tree(&gb, &h[i], 0, 0);        get_bits1(&gb);        if(h[i].current > 1) {            res = init_vlc(&vlc[i], SMKTREE_BITS, h[i].length,                    h[i].lengths, sizeof(int), sizeof(int),                    h[i].bits, sizeof(uint32_t), sizeof(uint32_t), INIT_VLC_LE);            if(res < 0) {                av_log(avctx, AV_LOG_ERROR, "Cannot build VLC table\n");                return -1;            }        }    }    if(bits) { //decode 16-bit data        pred[0]  = get_bits(&gb, 8);        pred[0] |= get_bits(&gb, 8);        *samples++ = pred[0];        if(stereo) {            pred[1]  = get_bits(&gb, 8);            pred[1] |= get_bits(&gb, 8);            *samples++ = pred[1];        }        for(i = 0; i < unp_size / 2; i++) {            if(i & stereo) {                if(vlc[2].table)                    res = get_vlc2(&gb, vlc[2].table, SMKTREE_BITS, 3);                else                    res = 0;                val  = h[2].values[res];                if(vlc[3].table)                    res = get_vlc2(&gb, vlc[3].table, SMKTREE_BITS, 3);                else                    res = 0;                val |= h[3].values[res] << 8;                pred[1] += (int16_t)val;                *samples++ = pred[1];            } else {                if(vlc[0].table)                    res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);                else                    res = 0;                val  = h[0].values[res];                if(vlc[1].table)                    res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3);                else                    res = 0;                val |= h[1].values[res] << 8;                pred[0] += val;                *samples++ = pred[0];            }        }    } else { //8-bit data        pred[0] = get_bits(&gb, 8);        *samples++ = (pred[0] - 0x80) << 8;        if(stereo) {            pred[1] = get_bits(&gb, 8);            *samples++ = (pred[1] - 0x80) << 8;        }        for(i = 0; i < unp_size; i++) {            if(i & stereo){                if(vlc[1].table)                    res = get_vlc2(&gb, vlc[1].table, SMKTREE_BITS, 3);                else                    res = 0;                pred[1] += (int8_t)h[1].values[res];                *samples++ = (pred[1] - 0x80) << 8;            } else {                if(vlc[0].table)                    res = get_vlc2(&gb, vlc[0].table, SMKTREE_BITS, 3);                else                    res = 0;                pred[0] += (int8_t)h[0].values[res];                *samples++ = (pred[0] - 0x80) << 8;            }        }        unp_size *= 2;    }    for(i = 0; i < 4; i++) {        if(vlc[i].table)            free_vlc(&vlc[i]);        if(h[i].bits)            av_free(h[i].bits);        if(h[i].lengths)            av_free(h[i].lengths);        if(h[i].values)            av_free(h[i].values);    }    *data_size = unp_size;    return buf_size;}AVCodec smacker_decoder = {    "smackvid",    CODEC_TYPE_VIDEO,    CODEC_ID_SMACKVIDEO,    sizeof(SmackVContext),    decode_init,    NULL,    decode_end,    decode_frame};AVCodec smackaud_decoder = {    "smackaud",    CODEC_TYPE_AUDIO,    CODEC_ID_SMACKAUDIO,    0,    smka_decode_init,    NULL,    NULL,    smka_decode_frame};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -