📄 encoder.c
字号:
image_destroy(&pEnc->vGMC, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); xvid_err_memory2a: xvid_free(pEnc->mbParam.mpeg_quant_matrices); xvid_err_memory2: xvid_free(pEnc->current->mbs); xvid_free(pEnc->reference->mbs); xvid_err_memory1: xvid_free(pEnc->current); xvid_free(pEnc->reference); xvid_err_memory1a: if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { xvid_free(pEnc->temp_dquants); } xvid_err_memory0: for (n=0; n<pEnc->num_plugins;n++) { if (pEnc->plugins[n].func) { pEnc->plugins[n].func(pEnc->plugins[n].param, XVID_PLG_DESTROY, 0, 0); } } xvid_free(pEnc->plugins); xvid_free(pEnc->zones); xvid_free(pEnc); create->handle = NULL; return XVID_ERR_MEMORY;}/***************************************************************************** * Encoder destruction * * This function destroy the entire encoder structure created by a previous * successful enc_create call. * * Returned values (for now only one returned value) : * - 0 - no errors * ****************************************************************************/intenc_destroy(Encoder * pEnc){ int i; /* B Frames specific */ for (i = 0; i < pEnc->mbParam.max_bframes+1; i++) { image_destroy(&pEnc->queue[i].image, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); } xvid_free(pEnc->queue); if (pEnc->mbParam.max_bframes > 0) { for (i = 0; i < pEnc->mbParam.max_bframes; i++) { if (pEnc->bframes[i] == NULL) continue; image_destroy(&pEnc->bframes[i]->image, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); xvid_free(pEnc->bframes[i]->mbs); xvid_free(pEnc->bframes[i]); } xvid_free(pEnc->bframes); } /* All images, reference, current etc ... */ image_destroy(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->reference->image, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->vInterH, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->vInterV, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->vInterHV, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->f_refh, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->f_refv, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->f_refhv, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->vGMC, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { image_destroy(&pEnc->sOriginal, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); image_destroy(&pEnc->sOriginal2, pEnc->mbParam.edged_width, pEnc->mbParam.edged_height); } /* Encoder structure */ xvid_free(pEnc->current->mbs); xvid_free(pEnc->current); xvid_free(pEnc->reference->mbs); xvid_free(pEnc->reference); if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { xvid_free(pEnc->temp_dquants); } if (pEnc->num_plugins>0) { xvid_plg_destroy_t pdestroy; memset(&pdestroy, 0, sizeof(xvid_plg_destroy_t)); pdestroy.version = XVID_VERSION; pdestroy.num_frames = pEnc->m_framenum; for (i=0; i<pEnc->num_plugins;i++) { if (pEnc->plugins[i].func) { pEnc->plugins[i].func(pEnc->plugins[i].param, XVID_PLG_DESTROY, &pdestroy, 0); } } xvid_free(pEnc->plugins); } xvid_free(pEnc->mbParam.mpeg_quant_matrices); if (pEnc->num_plugins>0) xvid_free(pEnc->zones); xvid_free(pEnc); return 0; /* ok */}/* call the plugins */static void call_plugins(Encoder * pEnc, FRAMEINFO * frame, IMAGE * original, int opt, int * type, int * quant, xvid_enc_stats_t * stats){ unsigned int i, j; xvid_plg_data_t data; /* set data struct */ memset(&data, 0, sizeof(xvid_plg_data_t)); data.version = XVID_VERSION; /* find zone */ for(i=0; i<pEnc->num_zones && pEnc->zones[i].frame<=frame->frame_num; i++) ; data.zone = i>0 ? &pEnc->zones[i-1] : NULL; data.width = pEnc->mbParam.width; data.height = pEnc->mbParam.height; data.mb_width = pEnc->mbParam.mb_width; data.mb_height = pEnc->mbParam.mb_height; data.fincr = frame->fincr; data.fbase = pEnc->mbParam.fbase; data.bquant_ratio = pEnc->mbParam.bquant_ratio; data.bquant_offset = pEnc->mbParam.bquant_offset; for (i=0; i<3; i++) { data.min_quant[i] = pEnc->mbParam.min_quant[i]; data.max_quant[i] = pEnc->mbParam.max_quant[i]; } data.reference.csp = XVID_CSP_PLANAR; data.reference.plane[0] = pEnc->reference->image.y; data.reference.plane[1] = pEnc->reference->image.u; data.reference.plane[2] = pEnc->reference->image.v; data.reference.stride[0] = pEnc->mbParam.edged_width; data.reference.stride[1] = pEnc->mbParam.edged_width/2; data.reference.stride[2] = pEnc->mbParam.edged_width/2; data.current.csp = XVID_CSP_PLANAR; data.current.plane[0] = frame->image.y; data.current.plane[1] = frame->image.u; data.current.plane[2] = frame->image.v; data.current.stride[0] = pEnc->mbParam.edged_width; data.current.stride[1] = pEnc->mbParam.edged_width/2; data.current.stride[2] = pEnc->mbParam.edged_width/2; data.frame_num = frame->frame_num; if (opt == XVID_PLG_BEFORE) { data.type = *type; data.quant = *quant; data.vol_flags = frame->vol_flags; data.vop_flags = frame->vop_flags; data.motion_flags = frame->motion_flags; } else if (opt == XVID_PLG_FRAME) { data.type = coding2type(frame->coding_type); data.quant = frame->quant; if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { data.dquant = pEnc->temp_dquants; data.dquant_stride = pEnc->mbParam.mb_width; memset(data.dquant, 0, data.mb_width*data.mb_height); } } else { /* XVID_PLG_AFTER */ if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { data.original.csp = XVID_CSP_PLANAR; data.original.plane[0] = original->y; data.original.plane[1] = original->u; data.original.plane[2] = original->v; data.original.stride[0] = pEnc->mbParam.edged_width; data.original.stride[1] = pEnc->mbParam.edged_width/2; data.original.stride[2] = pEnc->mbParam.edged_width/2; } if ((frame->vol_flags & XVID_VOL_EXTRASTATS) || (pEnc->mbParam.plugin_flags & XVID_REQPSNR)) { data.sse_y = plane_sse( original->y, frame->image.y, pEnc->mbParam.edged_width, pEnc->mbParam.width, pEnc->mbParam.height); data.sse_u = plane_sse( original->u, frame->image.u, pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2, pEnc->mbParam.height/2); data.sse_v = plane_sse( original->v, frame->image.v, pEnc->mbParam.edged_width/2, pEnc->mbParam.width/2, pEnc->mbParam.height/2); } data.type = coding2type(frame->coding_type); data.quant = frame->quant; if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { data.dquant = pEnc->temp_dquants; data.dquant_stride = pEnc->mbParam.mb_width; for (j=0; j<pEnc->mbParam.mb_height; j++) for (i=0; i<pEnc->mbParam.mb_width; i++) { data.dquant[j*data.dquant_stride + i] = frame->mbs[j*pEnc->mbParam.mb_width + i].dquant; } } data.vol_flags = frame->vol_flags; data.vop_flags = frame->vop_flags; data.motion_flags = frame->motion_flags; data.length = frame->length; data.kblks = frame->sStat.kblks; data.mblks = frame->sStat.mblks; data.ublks = frame->sStat.ublks; /* New code */ data.stats.type = coding2type(frame->coding_type); data.stats.quant = frame->quant; data.stats.vol_flags = frame->vol_flags; data.stats.vop_flags = frame->vop_flags; data.stats.length = frame->length; data.stats.hlength = frame->length - (frame->sStat.iTextBits / 8); data.stats.kblks = frame->sStat.kblks; data.stats.mblks = frame->sStat.mblks; data.stats.ublks = frame->sStat.ublks; data.stats.sse_y = data.sse_y; data.stats.sse_u = data.sse_u; data.stats.sse_v = data.sse_v; if (stats) *stats = data.stats; } /* call plugins */ for (i=0; i<(unsigned int)pEnc->num_plugins;i++) { emms(); if (pEnc->plugins[i].func) { if (pEnc->plugins[i].func(pEnc->plugins[i].param, opt, &data, 0) < 0) { continue; } } } emms(); /* copy modified values back into frame*/ if (opt == XVID_PLG_BEFORE) { *type = data.type; *quant = data.quant > 0 ? data.quant : 2; /* default */ frame->vol_flags = data.vol_flags; frame->vop_flags = data.vop_flags; frame->motion_flags = data.motion_flags; } else if (opt == XVID_PLG_FRAME) { if ((pEnc->mbParam.plugin_flags & XVID_REQDQUANTS)) { for (j=0; j<pEnc->mbParam.mb_height; j++) for (i=0; i<pEnc->mbParam.mb_width; i++) { frame->mbs[j*pEnc->mbParam.mb_width + i].dquant = data.dquant[j*data.mb_width + i]; } } else { for (j=0; j<pEnc->mbParam.mb_height; j++) for (i=0; i<pEnc->mbParam.mb_width; i++) { frame->mbs[j*pEnc->mbParam.mb_width + i].dquant = 0; } } frame->mbs[0].quant = data.quant; /* FRAME will not affect the quant in stats */ }}static __inline void inc_frame_num(Encoder * pEnc){ pEnc->current->frame_num = pEnc->m_framenum; pEnc->current->stamp = pEnc->mbParam.m_stamp; /* first frame is zero */ pEnc->mbParam.m_stamp += pEnc->current->fincr; pEnc->m_framenum++; /* debug ticker */}static __inline void dec_frame_num(Encoder * pEnc){ pEnc->mbParam.m_stamp -= pEnc->mbParam.fincr; pEnc->m_framenum--; /* debug ticker */}static __inline void MBSetDquant(MACROBLOCK * pMB, int x, int y, MBParam * mbParam){ if (pMB->cbp == 0) { /* we want to code dquant but the quantizer value will not be used yet let's find out if we can postpone dquant to next MB */ if (x == mbParam->mb_width-1 && y == mbParam->mb_height-1) { pMB->dquant = 0; /* it's the last MB of all, the easiest case */ return; } else { MACROBLOCK * next = pMB + 1; const MACROBLOCK * prev = pMB - 1; if (next->mode != MODE_INTER4V && next->mode != MODE_NOT_CODED) /* mode allows dquant change in the future */ if (abs(next->quant - prev->quant) <= 2) { /* quant change is not out of range */ pMB->quant = prev->quant; pMB->dquant = 0; next->dquant = next->quant - prev->quant; return; } } } /* couldn't skip this dquant */ pMB->mode = MODE_INTER_Q;} static __inline voidset_timecodes(FRAMEINFO* pCur,FRAMEINFO *pRef, int32_t time_base){ pCur->ticks = (int32_t)pCur->stamp % time_base; pCur->seconds = ((int32_t)pCur->stamp / time_base) - ((int32_t)pRef->stamp / time_base) ;#if 0 /* HEAVY DEBUG OUTPUT */ fprintf(stderr,"WriteVop: %d - %d \n", ((int32_t)pCur->stamp / time_base), ((int32_t)pRef->stamp / time_base)); fprintf(stderr,"set_timecodes: VOP %1d stamp=%lld ref_stamp=%lld base=%d\n", pCur->coding_type, pCur->stamp, pRef->stamp, time_base); fprintf(stderr,"set_timecodes: VOP %1d seconds=%d ticks=%d (ref-sec=%d ref-tick=%d)\n", pCur->coding_type, pCur->seconds, pCur->ticks, pRef->seconds, pRef->ticks);#endif}static intgcd(int a, int b){ int r ; if (b > a) { r = a; a = b; b = r; } while ((r = a % b)) { a = b; b = r; } return b;}static voidsimplify_par(int *par_width, int *par_height){ int _par_width = (!*par_width) ? 1 : (*par_width<0) ? -*par_width: *par_width; int _par_height = (!*par_height) ? 1 : (*par_height<0) ? -*par_height: *par_height; int divisor = gcd(_par_width, _par_height); _par_width /= divisor; _par_height /= divisor; /* 2^8 precision maximum */ if (_par_width>255 || _par_height>255) { float div; emms(); if (_par_width>_par_height) div = (float)_par_width/255; else div = (float)_par_height/255; _par_width = (int)((float)_par_width/div); _par_height = (int)((float)_par_height/div); } *par_width = _par_width; *par_height = _par_height; return;}/***************************************************************************** * IPB frame encoder entry point * * Returned values : * - >0 - output bytes * - 0 - no output * - XVID_ERR_VERSION - wrong version passed to core * - XVID_ERR_END - End of stream reached before end of coding * - XVID_ERR_FORMAT - the image subsystem reported the image had a wrong * format ****************************************************************************/intenc_encode(Encoder * pEnc, xvid_enc_frame_t * xFrame, xvid_enc_stats_t * stats){ xvid_enc_frame_t * frame; int type; Bitstream bs; if (XVID_VERSION_MAJOR(xFrame->version) != 1 || (stats && XVID_VERSION_MAJOR(stats->version) != 1)) /* v1.x.x */ return XVID_ERR_VERSION; xFrame->out_flags = 0; start_global_timer(); BitstreamInit(&bs, xFrame->bitstream, 0); /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * enqueue image to the encoding-queue * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ if (xFrame->input.csp != XVID_CSP_NULL) { QUEUEINFO * q = &pEnc->queue[pEnc->queue_tail]; start_timer(); if (image_input (&q->image, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width, (uint8_t**)xFrame->input.plane, xFrame->input.stride, xFrame->input.csp, xFrame->vol_flags & XVID_VOL_INTERLACING)) { emms(); return XVID_ERR_FORMAT; } stop_conv_timer(); if ((xFrame->vop_flags & XVID_VOP_CHROMAOPT)) { image_chroma_optimize(&q->image, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); } q->frame = *xFrame;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -