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

📄 dnxhdenc.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 2 页
字号:
        dsp->get_pixels(ctx->blocks[7], ptr_v + ctx->dct_uv_offset   , ctx->m.uvlinesize);    }}static av_always_inline int dnxhd_switch_matrix(DNXHDEncContext *ctx, int i){    if (i&2) {        ctx->m.q_intra_matrix16 = ctx->qmatrix_c16;        ctx->m.q_intra_matrix   = ctx->qmatrix_c;        return 1 + (i&1);    } else {        ctx->m.q_intra_matrix16 = ctx->qmatrix_l16;        ctx->m.q_intra_matrix   = ctx->qmatrix_l;        return 0;    }}static int dnxhd_calc_bits_thread(AVCodecContext *avctx, void *arg){    DNXHDEncContext *ctx = arg;    int mb_y, mb_x;    int qscale = ctx->thread[0]->qscale;    for (mb_y = ctx->m.start_mb_y; mb_y < ctx->m.end_mb_y; mb_y++) {        ctx->m.last_dc[0] =        ctx->m.last_dc[1] =        ctx->m.last_dc[2] = 1024;        for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) {            unsigned mb = mb_y * ctx->m.mb_width + mb_x;            int ssd     = 0;            int ac_bits = 0;            int dc_bits = 0;            int i;            dnxhd_get_blocks(ctx, mb_x, mb_y);            for (i = 0; i < 8; i++) {                DECLARE_ALIGNED_16(DCTELEM, block[64]);                DCTELEM *src_block = ctx->blocks[i];                int overflow, nbits, diff, last_index;                int n = dnxhd_switch_matrix(ctx, i);                memcpy(block, src_block, sizeof(block));                last_index = ctx->m.dct_quantize((MpegEncContext*)ctx, block, i, qscale, &overflow);                ac_bits += dnxhd_calc_ac_bits(ctx, block, last_index);                diff = block[0] - ctx->m.last_dc[n];                if (diff < 0) nbits = av_log2_16bit(-2*diff);                else          nbits = av_log2_16bit( 2*diff);                dc_bits += ctx->cid_table->dc_bits[nbits] + nbits;                ctx->m.last_dc[n] = block[0];                if (avctx->mb_decision == FF_MB_DECISION_RD || !RC_VARIANCE) {                    dnxhd_unquantize_c(ctx, block, i, qscale, last_index);                    ctx->m.dsp.idct(block);                    ssd += dnxhd_ssd_block(block, src_block);                }            }            ctx->mb_rc[qscale][mb].ssd = ssd;            ctx->mb_rc[qscale][mb].bits = ac_bits+dc_bits+12+8*ctx->table_vlc_bits[0];        }    }    return 0;}static int dnxhd_encode_thread(AVCodecContext *avctx, void *arg){    DNXHDEncContext *ctx = arg;    int mb_y, mb_x;    for (mb_y = ctx->m.start_mb_y; mb_y < ctx->m.end_mb_y; mb_y++) {        ctx->m.last_dc[0] =        ctx->m.last_dc[1] =        ctx->m.last_dc[2] = 1024;        for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) {            unsigned mb = mb_y * ctx->m.mb_width + mb_x;            int qscale = ctx->mb_qscale[mb];            int i;            put_bits(&ctx->m.pb, 12, qscale<<1);            dnxhd_get_blocks(ctx, mb_x, mb_y);            for (i = 0; i < 8; i++) {                DCTELEM *block = ctx->blocks[i];                int last_index, overflow;                int n = dnxhd_switch_matrix(ctx, i);                last_index = ctx->m.dct_quantize((MpegEncContext*)ctx, block, i, qscale, &overflow);                dnxhd_encode_block(ctx, block, last_index, n);            }        }        if (put_bits_count(&ctx->m.pb)&31)            put_bits(&ctx->m.pb, 32-(put_bits_count(&ctx->m.pb)&31), 0);    }    flush_put_bits(&ctx->m.pb);    return 0;}static void dnxhd_setup_threads_slices(DNXHDEncContext *ctx, uint8_t *buf){    int mb_y, mb_x;    int i, offset = 0;    for (i = 0; i < ctx->m.avctx->thread_count; i++) {        int thread_size = 0;        for (mb_y = ctx->thread[i]->m.start_mb_y; mb_y < ctx->thread[i]->m.end_mb_y; mb_y++) {            ctx->slice_size[mb_y] = 0;            for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) {                unsigned mb = mb_y * ctx->m.mb_width + mb_x;                ctx->slice_size[mb_y] += ctx->mb_bits[mb];            }            ctx->slice_size[mb_y] = (ctx->slice_size[mb_y]+31)&~31;            ctx->slice_size[mb_y] >>= 3;            thread_size += ctx->slice_size[mb_y];        }        init_put_bits(&ctx->thread[i]->m.pb, buf + 640 + offset, thread_size);        offset += thread_size;    }}static int dnxhd_mb_var_thread(AVCodecContext *avctx, void *arg){    DNXHDEncContext *ctx = arg;    int mb_y, mb_x;    for (mb_y = ctx->m.start_mb_y; mb_y < ctx->m.end_mb_y; mb_y++) {        for (mb_x = 0; mb_x < ctx->m.mb_width; mb_x++) {            unsigned mb  = mb_y * ctx->m.mb_width + mb_x;            uint8_t *pix = ctx->thread[0]->src[0] + ((mb_y<<4) * ctx->m.linesize) + (mb_x<<4);            int sum      = ctx->m.dsp.pix_sum(pix, ctx->m.linesize);            int varc     = (ctx->m.dsp.pix_norm1(pix, ctx->m.linesize) - (((unsigned)(sum*sum))>>8)+128)>>8;            ctx->mb_cmp[mb].value = varc;            ctx->mb_cmp[mb].mb = mb;        }    }    return 0;}static int dnxhd_encode_rdo(AVCodecContext *avctx, DNXHDEncContext *ctx){    int lambda, up_step, down_step;    int last_lower = INT_MAX, last_higher = 0;    int x, y, q;    for (q = 1; q < avctx->qmax; q++) {        ctx->qscale = q;        avctx->execute(avctx, dnxhd_calc_bits_thread, (void**)&ctx->thread[0], NULL, avctx->thread_count);    }    up_step = down_step = 2<<LAMBDA_FRAC_BITS;    lambda = ctx->lambda;    for (;;) {        int bits = 0;        int end = 0;        if (lambda == last_higher) {            lambda++;            end = 1; // need to set final qscales/bits        }        for (y = 0; y < ctx->m.mb_height; y++) {            for (x = 0; x < ctx->m.mb_width; x++) {                unsigned min = UINT_MAX;                int qscale = 1;                int mb = y*ctx->m.mb_width+x;                for (q = 1; q < avctx->qmax; q++) {                    unsigned score = ctx->mb_rc[q][mb].bits*lambda+(ctx->mb_rc[q][mb].ssd<<LAMBDA_FRAC_BITS);                    if (score < min) {                        min = score;                        qscale = q;                    }                }                bits += ctx->mb_rc[qscale][mb].bits;                ctx->mb_qscale[mb] = qscale;                ctx->mb_bits[mb] = ctx->mb_rc[qscale][mb].bits;            }            bits = (bits+31)&~31; // padding            if (bits > ctx->frame_bits)                break;        }        //dprintf(ctx->m.avctx, "lambda %d, up %u, down %u, bits %d, frame %d\n",        //        lambda, last_higher, last_lower, bits, ctx->frame_bits);        if (end) {            if (bits > ctx->frame_bits)                return -1;            break;        }        if (bits < ctx->frame_bits) {            last_lower = FFMIN(lambda, last_lower);            if (last_higher != 0)                lambda = (lambda+last_higher)>>1;            else                lambda -= down_step;            down_step *= 5; // XXX tune ?            up_step = 1<<LAMBDA_FRAC_BITS;            lambda = FFMAX(1, lambda);            if (lambda == last_lower)                break;        } else {            last_higher = FFMAX(lambda, last_higher);            if (last_lower != INT_MAX)                lambda = (lambda+last_lower)>>1;            else                lambda += up_step;            up_step *= 5;            down_step = 1<<LAMBDA_FRAC_BITS;        }    }    //dprintf(ctx->m.avctx, "out lambda %d\n", lambda);    ctx->lambda = lambda;    return 0;}static int dnxhd_find_qscale(DNXHDEncContext *ctx){    int bits = 0;    int up_step = 1;    int down_step = 1;    int last_higher = 0;    int last_lower = INT_MAX;    int qscale;    int x, y;    qscale = ctx->qscale;    for (;;) {        bits = 0;        ctx->qscale = qscale;        // XXX avoid recalculating bits        ctx->m.avctx->execute(ctx->m.avctx, dnxhd_calc_bits_thread, (void**)&ctx->thread[0], NULL, ctx->m.avctx->thread_count);        for (y = 0; y < ctx->m.mb_height; y++) {            for (x = 0; x < ctx->m.mb_width; x++)                bits += ctx->mb_rc[qscale][y*ctx->m.mb_width+x].bits;            bits = (bits+31)&~31; // padding            if (bits > ctx->frame_bits)                break;        }        //dprintf(ctx->m.avctx, "%d, qscale %d, bits %d, frame %d, higher %d, lower %d\n",        //        ctx->m.avctx->frame_number, qscale, bits, ctx->frame_bits, last_higher, last_lower);        if (bits < ctx->frame_bits) {            if (qscale == 1)                return 1;            if (last_higher == qscale - 1) {                qscale = last_higher;                break;            }            last_lower = FFMIN(qscale, last_lower);            if (last_higher != 0)                qscale = (qscale+last_higher)>>1;            else                qscale -= down_step++;            if (qscale < 1)                qscale = 1;            up_step = 1;        } else {            if (last_lower == qscale + 1)                break;            last_higher = FFMAX(qscale, last_higher);            if (last_lower != INT_MAX)                qscale = (qscale+last_lower)>>1;            else                qscale += up_step++;            down_step = 1;            if (qscale >= ctx->m.avctx->qmax)                return -1;        }    }    //dprintf(ctx->m.avctx, "out qscale %d\n", qscale);    ctx->qscale = qscale;    return 0;}static int dnxhd_rc_cmp(const void *a, const void *b){    return ((const RCCMPEntry *)b)->value - ((const RCCMPEntry *)a)->value;}static int dnxhd_encode_fast(AVCodecContext *avctx, DNXHDEncContext *ctx){    int max_bits = 0;    int ret, x, y;    if ((ret = dnxhd_find_qscale(ctx)) < 0)        return -1;    for (y = 0; y < ctx->m.mb_height; y++) {        for (x = 0; x < ctx->m.mb_width; x++) {            int mb = y*ctx->m.mb_width+x;            int delta_bits;            ctx->mb_qscale[mb] = ctx->qscale;            ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale][mb].bits;            max_bits += ctx->mb_rc[ctx->qscale][mb].bits;            if (!RC_VARIANCE) {                delta_bits = ctx->mb_rc[ctx->qscale][mb].bits-ctx->mb_rc[ctx->qscale+1][mb].bits;                ctx->mb_cmp[mb].mb = mb;                ctx->mb_cmp[mb].value = delta_bits ?                    ((ctx->mb_rc[ctx->qscale][mb].ssd-ctx->mb_rc[ctx->qscale+1][mb].ssd)*100)/delta_bits                    : INT_MIN; //avoid increasing qscale            }        }        max_bits += 31; //worst padding    }    if (!ret) {        if (RC_VARIANCE)            avctx->execute(avctx, dnxhd_mb_var_thread, (void**)&ctx->thread[0], NULL, avctx->thread_count);        qsort(ctx->mb_cmp, ctx->m.mb_num, sizeof(RCEntry), dnxhd_rc_cmp);        for (x = 0; x < ctx->m.mb_num && max_bits > ctx->frame_bits; x++) {            int mb = ctx->mb_cmp[x].mb;            max_bits -= ctx->mb_rc[ctx->qscale][mb].bits - ctx->mb_rc[ctx->qscale+1][mb].bits;            ctx->mb_qscale[mb] = ctx->qscale+1;            ctx->mb_bits[mb] = ctx->mb_rc[ctx->qscale+1][mb].bits;        }    }    return 0;}static void dnxhd_load_picture(DNXHDEncContext *ctx, const AVFrame *frame){    int i;    for (i = 0; i < 3; i++) {        ctx->frame.data[i]     = frame->data[i];        ctx->frame.linesize[i] = frame->linesize[i];    }    for (i = 0; i < ctx->m.avctx->thread_count; i++) {        ctx->thread[i]->m.linesize    = ctx->frame.linesize[0]<<ctx->interlaced;        ctx->thread[i]->m.uvlinesize  = ctx->frame.linesize[1]<<ctx->interlaced;        ctx->thread[i]->dct_y_offset  = ctx->m.linesize  *8;        ctx->thread[i]->dct_uv_offset = ctx->m.uvlinesize*8;    }    ctx->frame.interlaced_frame = frame->interlaced_frame;    ctx->cur_field = frame->interlaced_frame && !frame->top_field_first;}static int dnxhd_encode_picture(AVCodecContext *avctx, unsigned char *buf, int buf_size, const void *data){    DNXHDEncContext *ctx = avctx->priv_data;    int first_field = 1;    int offset, i, ret;    if (buf_size < ctx->cid_table->frame_size) {        av_log(avctx, AV_LOG_ERROR, "output buffer is too small to compress picture\n");        return -1;    }    dnxhd_load_picture(ctx, data); encode_coding_unit:    for (i = 0; i < 3; i++) {        ctx->src[i] = ctx->frame.data[i];        if (ctx->interlaced && ctx->cur_field)            ctx->src[i] += ctx->frame.linesize[i];    }    dnxhd_write_header(avctx, buf);    if (avctx->mb_decision == FF_MB_DECISION_RD)        ret = dnxhd_encode_rdo(avctx, ctx);    else        ret = dnxhd_encode_fast(avctx, ctx);    if (ret < 0) {        av_log(avctx, AV_LOG_ERROR, "picture could not fit ratecontrol constraints\n");        return -1;    }    dnxhd_setup_threads_slices(ctx, buf);    offset = 0;    for (i = 0; i < ctx->m.mb_height; i++) {        AV_WB32(ctx->msip + i * 4, offset);        offset += ctx->slice_size[i];        assert(!(ctx->slice_size[i] & 3));    }    avctx->execute(avctx, dnxhd_encode_thread, (void**)&ctx->thread[0], NULL, avctx->thread_count);    AV_WB32(buf + ctx->cid_table->coding_unit_size - 4, 0x600DC0DE); // EOF    if (ctx->interlaced && first_field) {        first_field     = 0;        ctx->cur_field ^= 1;        buf      += ctx->cid_table->coding_unit_size;        buf_size -= ctx->cid_table->coding_unit_size;        goto encode_coding_unit;    }    return ctx->cid_table->frame_size;}static int dnxhd_encode_end(AVCodecContext *avctx){    DNXHDEncContext *ctx = avctx->priv_data;    int i;    av_freep(&ctx->table_vlc_codes);    av_freep(&ctx->table_vlc_bits);    av_freep(&ctx->table_run_codes);    av_freep(&ctx->table_run_bits);    av_freep(&ctx->mb_bits);    av_freep(&ctx->mb_qscale);    av_freep(&ctx->mb_rc);    av_freep(&ctx->mb_cmp);    av_freep(&ctx->slice_size);    av_freep(&ctx->qmatrix_c);    av_freep(&ctx->qmatrix_l);    av_freep(&ctx->qmatrix_c16);    av_freep(&ctx->qmatrix_l16);    for (i = 1; i < avctx->thread_count; i++)        av_freep(&ctx->thread[i]);    return 0;}AVCodec dnxhd_encoder = {    "dnxhd",    CODEC_TYPE_VIDEO,    CODEC_ID_DNXHD,    sizeof(DNXHDEncContext),    dnxhd_encode_init,    dnxhd_encode_picture,    dnxhd_encode_end,    .pix_fmts = (enum PixelFormat[]){PIX_FMT_YUV422P, -1},};

⌨️ 快捷键说明

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