39 |
* MinChen <chenm001@163.com> |
* MinChen <chenm001@163.com> |
40 |
* 14.04.2002 added FrameCodeB() |
* 14.04.2002 added FrameCodeB() |
41 |
* |
* |
42 |
* $Id: encoder.c,v 1.76.2.26 2002-12-09 10:47:05 suxen_drol Exp $ |
* $Id: encoder.c,v 1.76.2.34 2003-01-05 16:18:47 syskin Exp $ |
43 |
* |
* |
44 |
****************************************************************************/ |
****************************************************************************/ |
45 |
|
|
73 |
****************************************************************************/ |
****************************************************************************/ |
74 |
|
|
75 |
#define ENC_CHECK(X) if(!(X)) return XVID_ERR_FORMAT |
#define ENC_CHECK(X) if(!(X)) return XVID_ERR_FORMAT |
76 |
#define SWAP(A,B) { void * tmp = A; A = B; B = tmp; } |
#define SWAP(_T_,A,B) { _T_ tmp = A; A = B; B = tmp; } |
77 |
|
|
78 |
/***************************************************************************** |
/***************************************************************************** |
79 |
* Local function prototypes |
* Local function prototypes |
646 |
|
|
647 |
|
|
648 |
|
|
649 |
|
/* convert pFrame->intra to coding_type */ |
650 |
|
static int intra2coding_type(int intra) |
651 |
|
{ |
652 |
|
if (intra < 0) return -1; |
653 |
|
if (intra == 1) return I_VOP; |
654 |
|
if (intra == 2) return B_VOP; |
655 |
|
|
656 |
|
return P_VOP; |
657 |
|
} |
658 |
|
|
659 |
|
|
660 |
|
|
661 |
/***************************************************************************** |
/***************************************************************************** |
674 |
{ |
{ |
675 |
uint16_t x, y; |
uint16_t x, y; |
676 |
Bitstream bs; |
Bitstream bs; |
677 |
uint32_t bits, mode; |
uint32_t bits; |
678 |
|
int mode; |
679 |
|
|
680 |
int input_valid = 1; |
int input_valid = 1; |
681 |
int bframes_count = 0; |
int bframes_count = 0; |
714 |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
715 |
|
|
716 |
pEnc->bframenum_tail--; |
pEnc->bframenum_tail--; |
717 |
SWAP(pEnc->current, pEnc->reference); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->reference); |
718 |
|
|
719 |
SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); |
720 |
|
|
721 |
FrameCodeP(pEnc, &bs, &bits, 1, 0); |
FrameCodeP(pEnc, &bs, &bits, 1, 0); |
722 |
bframes_count = 0; |
bframes_count = 0; |
792 |
if (pEnc->bframenum_dx50bvop != -1) |
if (pEnc->bframenum_dx50bvop != -1) |
793 |
{ |
{ |
794 |
|
|
795 |
SWAP(pEnc->current, pEnc->reference); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->reference); |
796 |
SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); |
797 |
|
|
798 |
if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { |
if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { |
799 |
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 IVOP"); |
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 IVOP"); |
807 |
|
|
808 |
} else if (input_valid) { |
} else if (input_valid) { |
809 |
|
|
810 |
SWAP(pEnc->current, pEnc->reference); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->reference); |
811 |
|
|
812 |
start_timer(); |
start_timer(); |
813 |
if (image_input |
if (image_input |
833 |
|
|
834 |
} else if (pEnc->queue_size > 0) { |
} else if (pEnc->queue_size > 0) { |
835 |
|
|
836 |
SWAP(pEnc->current, pEnc->reference); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->reference); |
837 |
|
|
838 |
image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head]); |
image_swap(&pEnc->current->image, &pEnc->queue[pEnc->queue_head]); |
839 |
pEnc->queue_head = (pEnc->queue_head + 1) % pEnc->mbParam.max_bframes; |
pEnc->queue_head = (pEnc->queue_head + 1) % pEnc->mbParam.max_bframes; |
866 |
// only inc frame num, adapt quant, etc. if we havent seen it before |
// only inc frame num, adapt quant, etc. if we havent seen it before |
867 |
if (pEnc->bframenum_dx50bvop < 0 ) |
if (pEnc->bframenum_dx50bvop < 0 ) |
868 |
{ |
{ |
869 |
|
mode = intra2coding_type(pFrame->intra); |
870 |
if (pFrame->quant == 0) |
if (pFrame->quant == 0) |
871 |
pEnc->current->quant = RateControlGetQ(&pEnc->rate_control, 0); |
pEnc->current->quant = RateControlGetQ(&pEnc->rate_control, 0); |
872 |
else |
else |
940 |
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
941 |
pEnc->iFrameNum++; |
pEnc->iFrameNum++; |
942 |
|
|
943 |
if (pEnc->iFrameNum == 0 || pFrame->intra == 1 || pEnc->bframenum_dx50bvop >= 0 || |
if (pEnc->iFrameNum == 0 || pEnc->bframenum_dx50bvop >= 0 || |
944 |
(pFrame->intra < 0 && pEnc->mbParam.iMaxKeyInterval > 0 && |
(mode < 0 && pEnc->mbParam.iMaxKeyInterval > 0 && |
945 |
pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval) |
pEnc->iFrameNum >= pEnc->mbParam.iMaxKeyInterval)) |
946 |
|| 2 == (mode = MEanalysis(&pEnc->reference->image, pEnc->current, |
{ |
947 |
|
mode = I_VOP; |
948 |
|
}else{ |
949 |
|
mode = MEanalysis(&pEnc->reference->image, pEnc->current, |
950 |
&pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval, |
&pEnc->mbParam, pEnc->mbParam.iMaxKeyInterval, |
951 |
(pFrame->intra < 0) ? pEnc->iFrameNum : 0, |
(mode < 0) ? pEnc->iFrameNum : 0, |
952 |
bframes_count++))) { |
bframes_count++); |
953 |
|
} |
954 |
|
|
955 |
|
if (mode == I_VOP) { |
956 |
/* |
/* |
957 |
* This will be coded as an Intra Frame |
* This will be coded as an Intra Frame |
958 |
*/ |
*/ |
986 |
pEnc->bframenum_tail--; |
pEnc->bframenum_tail--; |
987 |
pEnc->bframenum_dx50bvop = pEnc->bframenum_tail; |
pEnc->bframenum_dx50bvop = pEnc->bframenum_tail; |
988 |
|
|
989 |
SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); |
990 |
if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { |
if ((pEnc->mbParam.global & XVID_GLOBAL_DEBUG)) { |
991 |
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 BVOP->PVOP"); |
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 BVOP->PVOP"); |
992 |
} |
} |
1016 |
* NB : sequences like "IIBB" decode fine with msfdam but, |
* NB : sequences like "IIBB" decode fine with msfdam but, |
1017 |
* go screwy with divx 5.00 |
* go screwy with divx 5.00 |
1018 |
*/ |
*/ |
1019 |
} else if (pEnc->bframenum_tail >= pEnc->mbParam.max_bframes || mode != 0) { |
} else if (mode == P_VOP || pEnc->bframenum_tail >= pEnc->mbParam.max_bframes) { |
|
// } else if (pFrame->intra == 0 || pEnc->bframenum_tail >= pEnc->mbParam.max_bframes || mode != 0) { |
|
1020 |
/* |
/* |
1021 |
* This will be coded as a Predicted Frame |
* This will be coded as a Predicted Frame |
1022 |
*/ |
*/ |
1040 |
goto ipvop_loop; |
goto ipvop_loop; |
1041 |
} |
} |
1042 |
|
|
1043 |
} else { |
} else { /* mode == B_VOP */ |
1044 |
/* |
/* |
1045 |
* This will be coded as a Bidirectional Frame |
* This will be coded as a Bidirectional Frame |
1046 |
*/ |
*/ |
1067 |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant); |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size,pEnc->current->quant); |
1068 |
|
|
1069 |
/* store frame into bframe buffer & swap ref back to current */ |
/* store frame into bframe buffer & swap ref back to current */ |
1070 |
SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->bframes[pEnc->bframenum_tail]); |
1071 |
SWAP(pEnc->current, pEnc->reference); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->reference); |
1072 |
|
|
1073 |
pEnc->bframenum_tail++; |
pEnc->bframenum_tail++; |
1074 |
|
|
1148 |
ENC_CHECK(pFrame->bitstream); |
ENC_CHECK(pFrame->bitstream); |
1149 |
ENC_CHECK(pFrame->image); |
ENC_CHECK(pFrame->image); |
1150 |
|
|
1151 |
SWAP(pEnc->current, pEnc->reference); |
SWAP(FRAMEINFO *, pEnc->current, pEnc->reference); |
1152 |
|
|
1153 |
pEnc->current->global_flags = pFrame->general; |
pEnc->current->global_flags = pFrame->general; |
1154 |
pEnc->current->motion_flags = pFrame->motion; |
pEnc->current->motion_flags = pFrame->motion; |
1564 |
|
|
1565 |
BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); |
BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); |
1566 |
|
|
|
/* XXX: move this stuff to BitstreamWriteVolHeader */ |
|
|
#define DIVX501B481P "DivX501b481p" |
|
|
if ((pEnc->mbParam.global & XVID_GLOBAL_PACKED)) { |
|
|
BitstreamWriteUserData(bs, DIVX501B481P, strlen(DIVX501B481P)); |
|
|
} |
|
|
|
|
|
#define XVID_ID "XviD" XVID_BS_VERSION |
|
|
BitstreamWriteUserData(bs, XVID_ID, strlen(XVID_ID)); |
|
|
|
|
1567 |
set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase); |
set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase); |
1568 |
BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1); |
BitstreamWriteVopHeader(bs, &pEnc->mbParam, pEnc->current, 1); |
1569 |
|
|
1597 |
stop_coding_timer(); |
stop_coding_timer(); |
1598 |
} |
} |
1599 |
|
|
1600 |
|
if ((pEnc->current->global_flags & XVID_REDUCED)) |
1601 |
|
{ |
1602 |
|
image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width, |
1603 |
|
pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width, |
1604 |
|
16, XVID_DEC_DEBLOCKY|XVID_DEC_DEBLOCKUV); |
1605 |
|
} |
1606 |
emms(); |
emms(); |
1607 |
|
|
1608 |
*pBits = BitstreamPos(bs) - *pBits; |
*pBits = BitstreamPos(bs) - *pBits; |
1645 |
|
|
1646 |
if ((pEnc->current->global_flags & XVID_REDUCED)) |
if ((pEnc->current->global_flags & XVID_REDUCED)) |
1647 |
{ |
{ |
1648 |
// mb_width = (pEnc->mbParam.width + 31) / 32; |
mb_width = (pEnc->mbParam.width + 31) / 32; |
1649 |
// mb_height = (pEnc->mbParam.height + 31) / 32; |
mb_height = (pEnc->mbParam.height + 31) / 32; |
|
|
|
|
/* XXX: reduced resoltion not yet supported */ |
|
|
pEnc->current->global_flags &= ~XVID_REDUCED; |
|
1650 |
} |
} |
1651 |
|
|
1652 |
|
|
1683 |
pEnc->current->coding_type = P_VOP; |
pEnc->current->coding_type = P_VOP; |
1684 |
|
|
1685 |
start_timer(); |
start_timer(); |
1686 |
if (pEnc->current->global_flags & XVID_HINTEDME_SET) { |
if (pEnc->current->global_flags & XVID_HINTEDME_SET) |
1687 |
HintedMESet(pEnc, &bIntra); |
HintedMESet(pEnc, &bIntra); |
1688 |
if (bIntra == 0) { |
else |
|
pEnc->current->fcode = FindFcode(&pEnc->mbParam, pEnc->current); |
|
|
MotionEstimationHinted(&pEnc->mbParam, pEnc->current, pEnc->reference, |
|
|
&pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV); |
|
|
} |
|
|
|
|
|
} else { |
|
1689 |
|
|
1690 |
bIntra = |
bIntra = |
1691 |
MotionEstimation(&pEnc->mbParam, pEnc->current, pEnc->reference, |
MotionEstimation(&pEnc->mbParam, pEnc->current, pEnc->reference, |
1692 |
&pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, |
&pEnc->vInterH, &pEnc->vInterV, &pEnc->vInterHV, |
1693 |
iLimit); |
iLimit); |
1694 |
} |
|
1695 |
stop_motion_timer(); |
stop_motion_timer(); |
1696 |
|
|
1697 |
if (bIntra == 1) return FrameCodeI(pEnc, bs, pBits); |
if (bIntra == 1) return FrameCodeI(pEnc, bs, pBits); |
1838 |
} |
} |
1839 |
} |
} |
1840 |
|
|
1841 |
|
if ((pEnc->current->global_flags & XVID_REDUCED)) |
1842 |
|
{ |
1843 |
|
image_deblock_rrv(&pEnc->current->image, pEnc->mbParam.edged_width, |
1844 |
|
pEnc->current->mbs, mb_width, mb_height, pEnc->mbParam.mb_width, |
1845 |
|
16, XVID_DEC_DEBLOCKY|XVID_DEC_DEBLOCKUV); |
1846 |
|
} |
1847 |
|
|
1848 |
emms(); |
emms(); |
1849 |
|
|
1850 |
if (pEnc->current->global_flags & XVID_HINTEDME_GET) { |
if (pEnc->current->global_flags & XVID_HINTEDME_GET) { |
1913 |
} |
} |
1914 |
*/ |
*/ |
1915 |
|
|
1916 |
|
|
1917 |
*pBits = BitstreamPos(bs) - *pBits; |
*pBits = BitstreamPos(bs) - *pBits; |
1918 |
|
|
1919 |
return 0; // inter |
return 0; // inter |
1926 |
Bitstream * bs, |
Bitstream * bs, |
1927 |
uint32_t * pBits) |
uint32_t * pBits) |
1928 |
{ |
{ |
1929 |
int16_t dct_codes[6 * 64]; |
DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE); |
1930 |
int16_t qcoeff[6 * 64]; |
DECLARE_ALIGNED_MATRIX(qcoeff, 6, 64, int16_t, CACHE_LINE); |
1931 |
uint32_t x, y; |
uint32_t x, y; |
1932 |
|
|
1933 |
IMAGE *f_ref = &pEnc->reference->image; |
IMAGE *f_ref = &pEnc->reference->image; |