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

📄 roqvideoenc.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 3 页
字号:
                EVAL_MOTION(last_motion[offset]);            off[0]= (i/blocksize)*enc->width/blocksize + j/blocksize - 1;            off[1]= off[0] - enc->width/blocksize + 1;            off[2]= off[1] + 1;            if (i) {                for(k=0; k<2; k++)                    vect.d[k]= mid_pred(this_motion[off[0]].d[k],                                        this_motion[off[1]].d[k],                                        this_motion[off[2]].d[k]);                EVAL_MOTION(vect);                for(k=0; k<3; k++)                    EVAL_MOTION(this_motion[off[k]]);            } else if(j)                EVAL_MOTION(this_motion[off[0]]);            vect = bestpick;            oldbest = -1;            while (oldbest != lowestdiff) {                oldbest = lowestdiff;                for (k=0; k<8; k++) {                    vect2 = vect;                    vect2.d[0] += offsets[k].d[0];                    vect2.d[1] += offsets[k].d[1];                    EVAL_MOTION(vect2);                }                vect = bestpick;            }            offset = (i/blocksize)*enc->width/blocksize + j/blocksize;            this_motion[offset] = bestpick;        }}/** * Gets distortion for all options available to a subcel */static void gather_data_for_subcel(subcel_evaluation_t *subcel, int x,                                   int y, RoqContext *enc, roq_tempdata_t *tempData){    uint8_t mb4[4*4*3];    uint8_t mb2[2*2*3];    int cluster_index;    int i, best_dist;    static const int bitsUsed[4] = {2, 10, 10, 34};    if (enc->framesSinceKeyframe >= 1) {        subcel->motion = enc->this_motion4[y*enc->width/16 + x/4];        subcel->eval_dist[RoQ_ID_FCC] =            eval_motion_dist(enc, x, y,                             enc->this_motion4[y*enc->width/16 + x/4], 4);    } else        subcel->eval_dist[RoQ_ID_FCC] = INT_MAX;    if (enc->framesSinceKeyframe >= 2)        subcel->eval_dist[RoQ_ID_MOT] = block_sse(enc->frame_to_enc->data,                                                  enc->current_frame->data, x,                                                  y, x, y,                                                  enc->frame_to_enc->linesize,                                                  enc->current_frame->linesize,                                                  4);    else        subcel->eval_dist[RoQ_ID_MOT] = INT_MAX;    cluster_index = y*enc->width/16 + x/4;    get_frame_mb(enc->frame_to_enc, x, y, mb4, 4);    subcel->eval_dist[RoQ_ID_SLD] = index_mb(mb4,                                             tempData->codebooks.unpacked_cb4,                                             tempData->codebooks.numCB4,                                             &subcel->cbEntry, 4);    subcel->eval_dist[RoQ_ID_CCC] = 0;    for(i=0;i<4;i++) {        subcel->subCels[i] = tempData->closest_cb2[cluster_index*4+i];        get_frame_mb(enc->frame_to_enc, x+2*(i&1),                     y+(i&2), mb2, 2);        subcel->eval_dist[RoQ_ID_CCC] +=            squared_diff_macroblock(tempData->codebooks.unpacked_cb2 + subcel->subCels[i]*2*2*3, mb2, 2);    }    best_dist = INT_MAX;    for (i=0; i<4; i++)        if (ROQ_LAMBDA_SCALE*subcel->eval_dist[i] + enc->lambda*bitsUsed[i] <            best_dist) {            subcel->best_coding = i;            subcel->best_bit_use = bitsUsed[i];            best_dist = ROQ_LAMBDA_SCALE*subcel->eval_dist[i] +                enc->lambda*bitsUsed[i];        }}/** * Gets distortion for all options available to a cel */static void gather_data_for_cel(cel_evaluation_t *cel, RoqContext *enc,                                roq_tempdata_t *tempData){    uint8_t mb8[8*8*3];    int index = cel->sourceY*enc->width/64 + cel->sourceX/8;    int i, j, best_dist, divide_bit_use;    int bitsUsed[4] = {2, 10, 10, 0};    if (enc->framesSinceKeyframe >= 1) {        cel->motion = enc->this_motion8[index];        cel->eval_dist[RoQ_ID_FCC] =            eval_motion_dist(enc, cel->sourceX, cel->sourceY,                             enc->this_motion8[index], 8);    } else        cel->eval_dist[RoQ_ID_FCC] = INT_MAX;    if (enc->framesSinceKeyframe >= 2)        cel->eval_dist[RoQ_ID_MOT] = block_sse(enc->frame_to_enc->data,                                               enc->current_frame->data,                                               cel->sourceX, cel->sourceY,                                               cel->sourceX, cel->sourceY,                                               enc->frame_to_enc->linesize,                                               enc->current_frame->linesize,8);    else        cel->eval_dist[RoQ_ID_MOT] = INT_MAX;    get_frame_mb(enc->frame_to_enc, cel->sourceX, cel->sourceY, mb8, 8);    cel->eval_dist[RoQ_ID_SLD] =        index_mb(mb8, tempData->codebooks.unpacked_cb4_enlarged,                 tempData->codebooks.numCB4, &cel->cbEntry, 8);    gather_data_for_subcel(cel->subCels + 0, cel->sourceX+0, cel->sourceY+0, enc, tempData);    gather_data_for_subcel(cel->subCels + 1, cel->sourceX+4, cel->sourceY+0, enc, tempData);    gather_data_for_subcel(cel->subCels + 2, cel->sourceX+0, cel->sourceY+4, enc, tempData);    gather_data_for_subcel(cel->subCels + 3, cel->sourceX+4, cel->sourceY+4, enc, tempData);    cel->eval_dist[RoQ_ID_CCC] = 0;    divide_bit_use = 0;    for (i=0; i<4; i++) {        cel->eval_dist[RoQ_ID_CCC] +=            cel->subCels[i].eval_dist[cel->subCels[i].best_coding];        divide_bit_use += cel->subCels[i].best_bit_use;    }    best_dist = INT_MAX;    bitsUsed[3] = 2 + divide_bit_use;    for (i=0; i<4; i++)        if (ROQ_LAMBDA_SCALE*cel->eval_dist[i] + enc->lambda*bitsUsed[i] <            best_dist) {            cel->best_coding = i;            best_dist = ROQ_LAMBDA_SCALE*cel->eval_dist[i] +                enc->lambda*bitsUsed[i];        }    tempData->used_option[cel->best_coding]++;    tempData->mainChunkSize += bitsUsed[cel->best_coding];    if (cel->best_coding == RoQ_ID_SLD)        tempData->codebooks.usedCB4[cel->cbEntry]++;    if (cel->best_coding == RoQ_ID_CCC)        for (i=0; i<4; i++) {            if (cel->subCels[i].best_coding == RoQ_ID_SLD)                tempData->codebooks.usedCB4[cel->subCels[i].cbEntry]++;            else if (cel->subCels[i].best_coding == RoQ_ID_CCC)                for (j=0; j<4; j++)                    tempData->codebooks.usedCB2[cel->subCels[i].subCels[j]]++;        }}static void remap_codebooks(RoqContext *enc, roq_tempdata_t *tempData){    int i, j, idx=0;    /* Make remaps for the final codebook usage */    for (i=0; i<MAX_CBS_4x4; i++) {        if (tempData->codebooks.usedCB4[i]) {            tempData->i2f4[i] = idx;            tempData->f2i4[idx] = i;            for (j=0; j<4; j++)                tempData->codebooks.usedCB2[enc->cb4x4[i].idx[j]]++;            idx++;        }    }    tempData->numCB4 = idx;    idx = 0;    for (i=0; i<MAX_CBS_2x2; i++) {        if (tempData->codebooks.usedCB2[i]) {            tempData->i2f2[i] = idx;            tempData->f2i2[idx] = i;            idx++;        }    }    tempData->numCB2 = idx;}/** * Write codebook chunk */static void write_codebooks(RoqContext *enc, roq_tempdata_t *tempData){    int i, j;    uint8_t **outp= &enc->out_buf;    if (tempData->numCB2) {        bytestream_put_le16(outp, RoQ_QUAD_CODEBOOK);        bytestream_put_le32(outp, tempData->numCB2*6 + tempData->numCB4*4);        bytestream_put_byte(outp, tempData->numCB4);        bytestream_put_byte(outp, tempData->numCB2);        for (i=0; i<tempData->numCB2; i++) {            bytestream_put_buffer(outp, enc->cb2x2[tempData->f2i2[i]].y, 4);            bytestream_put_byte(outp, enc->cb2x2[tempData->f2i2[i]].u);            bytestream_put_byte(outp, enc->cb2x2[tempData->f2i2[i]].v);        }        for (i=0; i<tempData->numCB4; i++)            for (j=0; j<4; j++)                bytestream_put_byte(outp, tempData->i2f2[enc->cb4x4[tempData->f2i4[i]].idx[j]]);    }}static inline uint8_t motion_arg(motion_vect mot){    uint8_t ax = 8 - ((uint8_t) mot.d[0]);    uint8_t ay = 8 - ((uint8_t) mot.d[1]);    return ((ax&15)<<4) | (ay&15);}typedef struct{    int typeSpool;    int typeSpoolLength;    uint8_t argumentSpool[64];    uint8_t *args;    uint8_t **pout;} CodingSpool;/* NOTE: Typecodes must be spooled AFTER arguments!! */static void write_typecode(CodingSpool *s, uint8_t type){    s->typeSpool |= (type & 3) << (14 - s->typeSpoolLength);    s->typeSpoolLength += 2;    if (s->typeSpoolLength == 16) {        bytestream_put_le16(s->pout, s->typeSpool);        bytestream_put_buffer(s->pout, s->argumentSpool,                              s->args - s->argumentSpool);        s->typeSpoolLength = 0;        s->typeSpool = 0;        s->args = s->argumentSpool;    }}static void reconstruct_and_encode_image(RoqContext *enc, roq_tempdata_t *tempData, int w, int h, int numBlocks){    int i, j, k;    int x, y;    int subX, subY;    int dist=0;    roq_qcell *qcell;    cel_evaluation_t *eval;    CodingSpool spool;    spool.typeSpool=0;    spool.typeSpoolLength=0;    spool.args = spool.argumentSpool;    spool.pout = &enc->out_buf;    if (tempData->used_option[RoQ_ID_CCC]%2)        tempData->mainChunkSize+=8; //FIXME    /* Write the video chunk header */    bytestream_put_le16(&enc->out_buf, RoQ_QUAD_VQ);    bytestream_put_le32(&enc->out_buf, tempData->mainChunkSize/8);    bytestream_put_byte(&enc->out_buf, 0x0);    bytestream_put_byte(&enc->out_buf, 0x0);    for (i=0; i<numBlocks; i++) {        eval = tempData->cel_evals + i;        x = eval->sourceX;        y = eval->sourceY;        dist += eval->eval_dist[eval->best_coding];        switch (eval->best_coding) {        case RoQ_ID_MOT:            write_typecode(&spool, RoQ_ID_MOT);            break;        case RoQ_ID_FCC:            bytestream_put_byte(&spool.args, motion_arg(eval->motion));            write_typecode(&spool, RoQ_ID_FCC);            ff_apply_motion_8x8(enc, x, y,                                eval->motion.d[0], eval->motion.d[1]);            break;        case RoQ_ID_SLD:            bytestream_put_byte(&spool.args, tempData->i2f4[eval->cbEntry]);            write_typecode(&spool, RoQ_ID_SLD);            qcell = enc->cb4x4 + eval->cbEntry;            ff_apply_vector_4x4(enc, x  , y  , enc->cb2x2 + qcell->idx[0]);            ff_apply_vector_4x4(enc, x+4, y  , enc->cb2x2 + qcell->idx[1]);            ff_apply_vector_4x4(enc, x  , y+4, enc->cb2x2 + qcell->idx[2]);            ff_apply_vector_4x4(enc, x+4, y+4, enc->cb2x2 + qcell->idx[3]);            break;        case RoQ_ID_CCC:            write_typecode(&spool, RoQ_ID_CCC);            for (j=0; j<4; j++) {                subX = x + 4*(j&1);                subY = y + 2*(j&2);                switch(eval->subCels[j].best_coding) {                case RoQ_ID_MOT:                    break;                case RoQ_ID_FCC:                    bytestream_put_byte(&spool.args,                                        motion_arg(eval->subCels[j].motion));                    ff_apply_motion_4x4(enc, subX, subY,                                        eval->subCels[j].motion.d[0],                                        eval->subCels[j].motion.d[1]);                    break;                case RoQ_ID_SLD:                    bytestream_put_byte(&spool.args,                                        tempData->i2f4[eval->subCels[j].cbEntry]);                    qcell = enc->cb4x4 + eval->subCels[j].cbEntry;                    ff_apply_vector_2x2(enc, subX  , subY  ,                                        enc->cb2x2 + qcell->idx[0]);                    ff_apply_vector_2x2(enc, subX+2, subY  ,                                        enc->cb2x2 + qcell->idx[1]);                    ff_apply_vector_2x2(enc, subX  , subY+2,                                        enc->cb2x2 + qcell->idx[2]);                    ff_apply_vector_2x2(enc, subX+2, subY+2,                                        enc->cb2x2 + qcell->idx[3]);                    break;

⌨️ 快捷键说明

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