📄 encoder.c
字号:
if (xFrame->quant_intra_matrix) { memcpy(q->quant_intra_matrix, xFrame->quant_intra_matrix, 64*sizeof(unsigned char)); q->frame.quant_intra_matrix = q->quant_intra_matrix; } if (xFrame->quant_inter_matrix) { memcpy(q->quant_inter_matrix, xFrame->quant_inter_matrix, 64*sizeof(unsigned char)); q->frame.quant_inter_matrix = q->quant_inter_matrix; } pEnc->queue_tail = (pEnc->queue_tail + 1) % (pEnc->mbParam.max_bframes+1); pEnc->queue_size++; } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * bframe flush code * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */repeat: if (pEnc->flush_bframes) { if (pEnc->bframenum_head < pEnc->bframenum_tail) { DPRINTF(XVID_DEBUG_DEBUG,"*** BFRAME (flush) bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { image_copy(&pEnc->sOriginal2, &pEnc->bframes[pEnc->bframenum_head]->image, pEnc->mbParam.edged_width, pEnc->mbParam.height); } FrameCodeB(pEnc, pEnc->bframes[pEnc->bframenum_head], &bs); call_plugins(pEnc, pEnc->bframes[pEnc->bframenum_head], &pEnc->sOriginal2, XVID_PLG_AFTER, 0, 0, stats); pEnc->bframenum_head++; goto done; } /* write an empty marker to the bitstream. for divx5 decoder compatibility, this marker must consist of a not-coded p-vop, with a time_base of zero, and time_increment indentical to the future-referece frame. */ if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED && pEnc->bframenum_tail > 0)) { int tmp; int bits; DPRINTF(XVID_DEBUG_DEBUG,"*** EMPTY bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); bits = BitstreamPos(&bs); tmp = pEnc->current->seconds; pEnc->current->seconds = 0; /* force time_base = 0 */ BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0, pEnc->current->quant); BitstreamPad(&bs); pEnc->current->seconds = tmp; /* add the not-coded length to the reference frame size */ pEnc->current->length += (BitstreamPos(&bs) - bits) / 8; call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats); /* flush complete: reset counters */ pEnc->flush_bframes = 0; pEnc->bframenum_head = pEnc->bframenum_tail = 0; goto done; } /* flush complete: reset counters */ pEnc->flush_bframes = 0; pEnc->bframenum_head = pEnc->bframenum_tail = 0; } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * dequeue frame from the encoding queue * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ if (pEnc->queue_size == 0) /* empty */ { if (xFrame->input.csp == XVID_CSP_NULL) /* no futher input */ { DPRINTF(XVID_DEBUG_DEBUG,"*** FINISH bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); if (!(pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->mbParam.max_bframes > 0) { call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats); } /* if the very last frame is to be b-vop, we must change it to a p-vop */ if (pEnc->bframenum_tail > 0) { SWAP(FRAMEINFO*, pEnc->current, pEnc->reference); pEnc->bframenum_tail--; SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); /* convert B-VOP to P-VOP */ pEnc->current->quant = 100*pEnc->current->quant - pEnc->mbParam.bquant_offset; pEnc->current->quant += pEnc->mbParam.bquant_ratio - 1; /* to avoid rouding issues */ pEnc->current->quant /= pEnc->mbParam.bquant_ratio; if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { image_copy(&pEnc->sOriginal, &pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height); } DPRINTF(XVID_DEBUG_DEBUG,"*** PFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); pEnc->mbParam.frame_drop_ratio = -1; /* it must be a coded vop */ FrameCodeP(pEnc, &bs); if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail==0) { call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats); }else{ pEnc->flush_bframes = 1; goto done; } } DPRINTF(XVID_DEBUG_DEBUG, "*** END\n"); emms(); return XVID_ERR_END; /* end of stream reached */ } goto done; /* nothing to encode yet; encoder lag */ } /* the current FRAME becomes the reference */ SWAP(FRAMEINFO*, pEnc->current, pEnc->reference); /* remove frame from encoding-queue (head), and move it into the current */ image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image); frame = &pEnc->queue[pEnc->queue_head].frame; pEnc->queue_head = (pEnc->queue_head + 1) % (pEnc->mbParam.max_bframes+1); pEnc->queue_size--; /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * init pEnc->current fields * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ pEnc->current->fincr = pEnc->mbParam.fincr>0 ? pEnc->mbParam.fincr : frame->fincr; inc_frame_num(pEnc); pEnc->current->vol_flags = frame->vol_flags; pEnc->current->vop_flags = frame->vop_flags; pEnc->current->motion_flags = frame->motion; pEnc->current->fcode = pEnc->mbParam.m_fcode; pEnc->current->bcode = pEnc->mbParam.m_fcode; if ((xFrame->vop_flags & XVID_VOP_CHROMAOPT)) { image_chroma_optimize(&pEnc->current->image, pEnc->mbParam.width, pEnc->mbParam.height, pEnc->mbParam.edged_width); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * frame type & quant selection * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ type = frame->type; pEnc->current->quant = frame->quant; call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_BEFORE, &type, &pEnc->current->quant, stats); if (type > 0){ /* XVID_TYPE_?VOP */ type = type2coding(type); /* convert XVID_TYPE_?VOP to bitstream coding type */ } else{ /* XVID_TYPE_AUTO */ if (pEnc->iFrameNum == 0 || (pEnc->mbParam.iMaxKeyInterval > 0 && pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)){ pEnc->iFrameNum = 0; type = I_VOP; }else{ type = MEanalysis(&pEnc->reference->image, pEnc->current, &pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval, pEnc->iFrameNum, pEnc->bframenum_tail, xFrame->bframe_threshold, (pEnc->bframes) ? pEnc->bframes[pEnc->bframenum_head]->mbs: NULL); } } if (type != I_VOP) pEnc->current->vol_flags = pEnc->mbParam.vol_flags; /* don't allow VOL changes here */ /* bframes buffer overflow check */ if (type == B_VOP && pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) { type = P_VOP; } pEnc->iFrameNum++; if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5, "%d st:%lld if:%d", pEnc->current->frame_num, pEnc->current->stamp, pEnc->iFrameNum); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * encode this frame as a b-vop * (we dont encode here, rather we store the frame in the bframes queue, to be encoded later) * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ if (type == B_VOP) { if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP"); } if (frame->quant < 1) { pEnc->current->quant = ((((pEnc->reference->quant + pEnc->current->quant) * pEnc->mbParam.bquant_ratio) / 2) + pEnc->mbParam.bquant_offset)/100; } else { pEnc->current->quant = frame->quant; } if (pEnc->current->quant < 1) pEnc->current->quant = 1; else if (pEnc->current->quant > 31) pEnc->current->quant = 31; DPRINTF(XVID_DEBUG_DEBUG,"*** BFRAME (store) bf: head=%i tail=%i queue: head=%i tail=%i size=%i quant=%i\n", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant); /* store frame into bframe buffer & swap ref back to current */ SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); SWAP(FRAMEINFO*, pEnc->current, pEnc->reference); pEnc->bframenum_tail++; goto repeat; } DPRINTF(XVID_DEBUG_DEBUG,"*** XXXXXX bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); /* for unpacked bframes, output the stats for the last encoded frame */ if (!(pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->mbParam.max_bframes > 0) { if (pEnc->current->stamp > 0) { call_plugins(pEnc, pEnc->reference, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats); } else stats->type = XVID_TYPE_NOTHING; } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * closed-gop * if the frame prior to an iframe is scheduled as a bframe, we must change it to a pframe * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ if (type == I_VOP && (pEnc->mbParam.global_flags & XVID_GLOBAL_CLOSED_GOP) && pEnc->bframenum_tail > 0) { /* place this frame back on the encoding-queue (head) */ /* we will deal with it next time */ dec_frame_num(pEnc); pEnc->iFrameNum--; pEnc->queue_head = (pEnc->queue_head + (pEnc->mbParam.max_bframes+1) - 1) % (pEnc->mbParam.max_bframes+1); pEnc->queue_size++; image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head].image); /* grab the last frame from the bframe-queue */ pEnc->bframenum_tail--; SWAP(FRAMEINFO*, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "CLOSED GOP BVOP->PVOP"); } /* convert B-VOP quant to P-VOP */ pEnc->current->quant = 100*pEnc->current->quant - pEnc->mbParam.bquant_offset; pEnc->current->quant += pEnc->mbParam.bquant_ratio - 1; /* to avoid rouding issues */ pEnc->current->quant /= pEnc->mbParam.bquant_ratio; type = P_VOP; } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * encode this frame as an i-vop * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ if (type == I_VOP) { DPRINTF(XVID_DEBUG_DEBUG,"*** IFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "IVOP"); } pEnc->iFrameNum = 1; /* ---- update vol flags at IVOP ----------- */ pEnc->mbParam.vol_flags = pEnc->current->vol_flags; /* Aspect ratio */ switch(frame->par) { case XVID_PAR_11_VGA: case XVID_PAR_43_PAL: case XVID_PAR_43_NTSC: case XVID_PAR_169_PAL: case XVID_PAR_169_NTSC: case XVID_PAR_EXT: pEnc->mbParam.par = frame->par; break; default: pEnc->mbParam.par = XVID_PAR_11_VGA; break; } /* For extended PAR only, we try to sanityse/simplify par values */ if (pEnc->mbParam.par == XVID_PAR_EXT) { pEnc->mbParam.par_width = frame->par_width; pEnc->mbParam.par_height = frame->par_height; simplify_par(&pEnc->mbParam.par_width, &pEnc->mbParam.par_height); } if ((pEnc->mbParam.vol_flags & XVID_VOL_MPEGQUANT)) { if (frame->quant_intra_matrix != NULL) set_intra_matrix(pEnc->mbParam.mpeg_quant_matrices, frame->quant_intra_matrix); if (frame->quant_inter_matrix != NULL) set_inter_matrix(pEnc->mbParam.mpeg_quant_matrices, frame->quant_inter_matrix); } /* prevent vol/vop misuse */ if (!(pEnc->current->vol_flags & XVID_VOL_INTERLACING)) pEnc->current->vop_flags &= ~(XVID_VOP_TOPFIELDFIRST|XVID_VOP_ALTERNATESCAN); /* ^^^------------------------ */ if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { image_copy(&pEnc->sOriginal, &pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height); } FrameCodeI(pEnc, &bs); xFrame->out_flags |= XVID_KEYFRAME; /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * encode this frame as an p-vop * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ } else { /* (type == P_VOP || type == S_VOP) */ DPRINTF(XVID_DEBUG_DEBUG,"*** PFRAME bf: head=%i tail=%i queue: head=%i tail=%i size=%i\n", pEnc->bframenum_head, pEnc->bframenum_tail, pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); if ((pEnc->current->vop_flags & XVID_VOP_DEBUG)) { image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "PVOP"); } if ((pEnc->mbParam.plugin_flags & XVID_REQORIGINAL)) { image_copy(&pEnc->sOriginal, &pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height); } if ( FrameCodeP(pEnc, &bs) == 0 ) { /* N-VOP, we mustn't code b-frames yet */ call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats); goto done; } } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * on next enc_encode call we must flush bframes * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% *//*done_flush:*/ pEnc->flush_bframes = 1; /* packed & queued_bframes: dont bother outputting stats here, we do so after the flush */ if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail > 0) { goto repeat; } /* packed or no-bframes or no-bframes-queued: output stats */ if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) || pEnc->mbParam.max_bframes == 0 ) { call_plugins(pEnc, pEnc->current, &pEnc->sOriginal, XVID_PLG_AFTER, 0, 0, stats); } /* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% * done; return number of bytes consumed * %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */done: stop_global_timer(); write_timer(); emms(); return BitstreamLength(&bs);}static void SetMacroblockQuants(MBParam * const pParam, FRAMEINFO * frame){ unsigned int i; MACROBLOCK * pMB = frame->mbs; int quant = frame->mbs[0].quant; /* set by XVID_PLG_FRAME */ if (quant > 31) frame->quant = quant = 31; else if (quant < 1) frame->quant = quant = 1; for (i = 0; i < pParam->mb_height * pParam->mb_width; i++) { quant += pMB->dquant; if (quant > 31) quant = 31; else if (quant < 1) quant = 1; pMB->quant = quant; pMB++; }}static __inline voidCodeIntraMB(Encoder * pEnc, MACROBLOCK * pMB){ pMB->mode = MODE_INTRA; /* zero mv statistics */ pMB->mvs[0].x = pMB->mvs[1].x = pMB->mvs[2].x = pMB->mvs[3].x = 0; pMB->mvs[0].y = pMB->mvs[1].y = pMB->mvs[2].y = pMB->mvs[3].y = 0; pMB->sad8[0] = pMB->sad8[1] = pMB->sad8[2] = pMB->sad8[3] = 0; pMB->sad16 = 0; if (pMB->dquant != 0) { pMB->mode = MODE_INTRA_Q; }}static intFrameCodeI(Encoder * pEnc, Bitstream * bs){ int bits = BitstreamPos(bs); int mb_width = pEnc->mbParam.mb_width; int mb_height = pEnc->mbParam.mb_height; DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE); DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); uint16_t x, y; pEnc->mbParam.m_rounding_type = 1; pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type; pEnc->current->coding_type = I_VOP; call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_FRAME, NULL, NULL, NULL); SetMacroblockQuants(&pEnc->mbParam, pEnc->current); BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase); BitstreamPad(bs); BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1, pEnc->current->mbs[0].quant); pEnc->current->sStat.iTextBits = 0; pEnc->current->sStat.kblks = mb_width * mb_height; pEnc->current->sStat.mblks = pEnc->current->sStat.ublks = 0; for (y = 0; y < mb_height; y++) for (x = 0; x < mb_width; x++) { MACROBLOCK *pMB = &pEnc->current->mbs[x + y * pEnc->mbParam.mb_width];
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -