37 |
* MinChen <chenm001@163.com> |
* MinChen <chenm001@163.com> |
38 |
* 14.04.2002 added FrameCodeB() |
* 14.04.2002 added FrameCodeB() |
39 |
* |
* |
40 |
* $Id: encoder.c,v 1.45 2002-06-22 07:23:10 suxen_drol Exp $ |
* $Id: encoder.c,v 1.50 2002-06-28 15:14:40 suxen_drol Exp $ |
41 |
* |
* |
42 |
****************************************************************************/ |
****************************************************************************/ |
43 |
|
|
51 |
#include "global.h" |
#include "global.h" |
52 |
#include "utils/timer.h" |
#include "utils/timer.h" |
53 |
#include "image/image.h" |
#include "image/image.h" |
54 |
|
#ifdef BFRAMES |
55 |
|
#include "image/font.h" |
56 |
|
#endif |
57 |
#include "motion/motion.h" |
#include "motion/motion.h" |
58 |
#include "bitstream/cbp.h" |
#include "bitstream/cbp.h" |
59 |
#include "utils/mbfunctions.h" |
#include "utils/mbfunctions.h" |
333 |
/* B Frames specific init */ |
/* B Frames specific init */ |
334 |
#ifdef BFRAMES |
#ifdef BFRAMES |
335 |
|
|
336 |
pEnc->packed = pParam->packed; |
pEnc->global = pParam->global; |
337 |
pEnc->mbParam.max_bframes = pParam->max_bframes; |
pEnc->mbParam.max_bframes = pParam->max_bframes; |
338 |
pEnc->bquant_ratio = pParam->bquant_ratio; |
pEnc->bquant_ratio = pParam->bquant_ratio; |
339 |
pEnc->bframes = NULL; |
pEnc->bframes = NULL; |
378 |
pEnc->bframenum_head = 0; |
pEnc->bframenum_head = 0; |
379 |
pEnc->bframenum_tail = 0; |
pEnc->bframenum_tail = 0; |
380 |
pEnc->flush_bframes = 0; |
pEnc->flush_bframes = 0; |
381 |
|
pEnc->bframenum_dx50bvop = -1; |
382 |
|
|
383 |
pEnc->queue = NULL; |
pEnc->queue = NULL; |
384 |
|
|
412 |
|
|
413 |
pEnc->mbParam.m_seconds = 0; |
pEnc->mbParam.m_seconds = 0; |
414 |
pEnc->mbParam.m_ticks = 0; |
pEnc->mbParam.m_ticks = 0; |
415 |
|
pEnc->m_framenum = 0; |
416 |
#endif |
#endif |
417 |
|
|
418 |
pParam->handle = (void *) pEnc; |
pParam->handle = (void *) pEnc; |
613 |
{ |
{ |
614 |
pEnc->iFrameNum++; |
pEnc->iFrameNum++; |
615 |
pEnc->mbParam.m_ticks += pEnc->mbParam.fincr; |
pEnc->mbParam.m_ticks += pEnc->mbParam.fincr; |
616 |
if (pEnc->mbParam.m_ticks > pEnc->mbParam.fbase) { |
|
617 |
pEnc->mbParam.m_seconds = pEnc->mbParam.m_ticks % pEnc->mbParam.fbase; |
pEnc->mbParam.m_seconds = pEnc->mbParam.m_ticks / pEnc->mbParam.fbase; |
618 |
pEnc->mbParam.m_ticks = pEnc->mbParam.m_ticks % pEnc->mbParam.fbase; |
pEnc->mbParam.m_ticks = pEnc->mbParam.m_ticks % pEnc->mbParam.fbase; |
619 |
} |
} |
|
} |
|
620 |
#endif |
#endif |
621 |
|
|
622 |
|
|
736 |
if (pEnc->bframenum_head > 0) { |
if (pEnc->bframenum_head > 0) { |
737 |
pEnc->bframenum_head = pEnc->bframenum_tail = 0; |
pEnc->bframenum_head = pEnc->bframenum_tail = 0; |
738 |
|
|
739 |
if (pEnc->packed) { |
if ((pEnc->global & XVID_GLOBAL_PACKED)) { |
740 |
|
|
741 |
DPRINTF("*** EMPTY bf: head=%i tail=%i queue: head=%i tail=%i size=%i", |
DPRINTF("*** EMPTY bf: head=%i tail=%i queue: head=%i tail=%i size=%i", |
742 |
pEnc->bframenum_head, pEnc->bframenum_tail, |
pEnc->bframenum_head, pEnc->bframenum_tail, |
743 |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
744 |
|
|
|
|
|
745 |
BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0); |
BitstreamWriteVopHeader(&bs, &pEnc->mbParam, pEnc->current, 0); |
746 |
BitstreamPad(&bs); |
BitstreamPad(&bs); |
747 |
BitstreamPutBits(&bs, 0x7f, 8); |
BitstreamPutBits(&bs, 0x7f, 8); |
759 |
|
|
760 |
bvop_loop: |
bvop_loop: |
761 |
|
|
762 |
if (input_valid) { |
if (pEnc->bframenum_dx50bvop != -1) |
763 |
|
{ |
764 |
|
|
765 |
|
SWAP(pEnc->current, pEnc->reference); |
766 |
|
SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); |
767 |
|
|
768 |
|
if ((pEnc->global & XVID_GLOBAL_DEBUG)) { |
769 |
|
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 IVOP"); |
770 |
|
} |
771 |
|
|
772 |
|
if (input_valid) |
773 |
|
{ |
774 |
|
queue_image(pEnc, pFrame); |
775 |
|
input_valid = 0; |
776 |
|
} |
777 |
|
|
778 |
|
} else if (input_valid) { |
779 |
|
|
780 |
SWAP(pEnc->current, pEnc->reference); |
SWAP(pEnc->current, pEnc->reference); |
781 |
|
|
812 |
pEnc->bframenum_head, pEnc->bframenum_tail, |
pEnc->bframenum_head, pEnc->bframenum_tail, |
813 |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
814 |
|
|
|
|
|
815 |
pFrame->intra = 0; |
pFrame->intra = 0; |
816 |
|
|
817 |
BitstreamPutBits(&bs, 0x7f, 8); |
BitstreamPutBits(&bs, 0x7f, 8); |
833 |
* comment style :-) |
* comment style :-) |
834 |
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
835 |
|
|
|
//$$ SWAP(pEnc->current, pEnc->reference); |
|
|
|
|
836 |
emms(); |
emms(); |
837 |
|
|
838 |
|
// only inc frame num, adapt quant, etc. if we havent seen it before |
839 |
|
if (pEnc->bframenum_dx50bvop < 0 ) |
840 |
|
{ |
841 |
if (pFrame->quant == 0) |
if (pFrame->quant == 0) |
842 |
pEnc->current->quant = RateControlGetQ(&pEnc->rate_control, 0); |
pEnc->current->quant = RateControlGetQ(&pEnc->rate_control, 0); |
843 |
else |
else |
851 |
|
|
852 |
pEnc->current->global_flags = pFrame->general; |
pEnc->current->global_flags = pFrame->general; |
853 |
pEnc->current->motion_flags = pFrame->motion; |
pEnc->current->motion_flags = pFrame->motion; |
854 |
pEnc->current->seconds = pEnc->mbParam.m_seconds; |
|
|
pEnc->current->ticks = pEnc->mbParam.m_ticks; |
|
855 |
/* ToDo : dynamic fcode (in both directions) */ |
/* ToDo : dynamic fcode (in both directions) */ |
856 |
pEnc->current->fcode = pEnc->mbParam.m_fcode; |
pEnc->current->fcode = pEnc->mbParam.m_fcode; |
857 |
pEnc->current->bcode = pEnc->mbParam.m_fcode; |
pEnc->current->bcode = pEnc->mbParam.m_fcode; |
858 |
|
|
859 |
//$$$ start_timer(); |
pEnc->current->seconds = pEnc->mbParam.m_seconds; |
860 |
//$$$ if (image_input |
pEnc->current->ticks = pEnc->mbParam.m_ticks; |
861 |
//$$$ (&pEnc->current->image, pEnc->mbParam.width, pEnc->mbParam.height, |
|
862 |
//$$$ pEnc->mbParam.edged_width, pFrame->image, pFrame->colorspace)) |
inc_frame_num(pEnc); |
|
//$$$ return XVID_ERR_FORMAT; |
|
|
//$$$ stop_conv_timer(); |
|
863 |
|
|
864 |
#ifdef _DEBUG_PSNR |
#ifdef _DEBUG_PSNR |
865 |
image_copy(&pEnc->sOriginal, &pEnc->current->image, |
image_copy(&pEnc->sOriginal, &pEnc->current->image, |
868 |
|
|
869 |
emms(); |
emms(); |
870 |
|
|
871 |
|
if ((pEnc->global & XVID_GLOBAL_DEBUG)) { |
872 |
|
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 5, |
873 |
|
"%i if:%i st:%i:%i", pEnc->m_framenum++, pEnc->iFrameNum, pEnc->current->seconds, pEnc->current->ticks); |
874 |
|
} |
875 |
|
|
876 |
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
877 |
* Luminance masking |
* Luminance masking |
878 |
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
902 |
} |
} |
903 |
|
|
904 |
#undef OFFSET |
#undef OFFSET |
|
|
|
905 |
} |
} |
906 |
|
|
907 |
xvid_free(temp_dquants); |
xvid_free(temp_dquants); |
908 |
} |
} |
909 |
|
|
910 |
|
} |
911 |
|
|
912 |
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% |
913 |
* ivop/pvop/bvop selection |
* ivop/pvop/bvop selection |
914 |
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% */ |
915 |
|
|
916 |
|
|
917 |
if (pEnc->iFrameNum == 0 || pFrame->intra == 1 || |
if (pEnc->iFrameNum == 0 || pFrame->intra == 1 || pEnc->bframenum_dx50bvop >= 0 || |
918 |
(pFrame->intra < 0 && pEnc->iMaxKeyInterval > 0 && |
(pFrame->intra < 0 && pEnc->iMaxKeyInterval > 0 && |
919 |
pEnc->iFrameNum >= pEnc->iMaxKeyInterval) |
pEnc->iFrameNum >= pEnc->iMaxKeyInterval) |
920 |
|| image_mad(&pEnc->reference->image, &pEnc->current->image, |
|| image_mad(&pEnc->reference->image, &pEnc->current->image, |
928 |
pEnc->bframenum_head, pEnc->bframenum_tail, |
pEnc->bframenum_head, pEnc->bframenum_tail, |
929 |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
930 |
|
|
931 |
FrameCodeI(pEnc, &bs, &bits); |
if ((pEnc->global & XVID_GLOBAL_DEBUG)) { |
932 |
|
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "IVOP"); |
933 |
|
} |
934 |
|
|
935 |
|
// when we reach an iframe in DX50BVOP mode, encode the last bframe as a pframe |
936 |
|
|
937 |
|
if ((pEnc->global & XVID_GLOBAL_DX50BVOP) && pEnc->bframenum_tail > 0) { |
938 |
|
|
939 |
|
pEnc->bframenum_tail--; |
940 |
|
pEnc->bframenum_dx50bvop = pEnc->bframenum_tail; |
941 |
|
|
942 |
|
SWAP(pEnc->current, pEnc->bframes[pEnc->bframenum_dx50bvop]); |
943 |
|
if ((pEnc->global & XVID_GLOBAL_DEBUG)) { |
944 |
|
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 100, "DX50 BVOP->PVOP"); |
945 |
|
} |
946 |
|
FrameCodeP(pEnc, &bs, &bits, 1, 0); |
947 |
|
|
948 |
|
pFrame->intra = 0; |
949 |
|
|
950 |
|
} else { |
951 |
|
|
952 |
|
FrameCodeI(pEnc, &bs, &bits); |
953 |
pFrame->intra = 1; |
pFrame->intra = 1; |
|
pEnc->flush_bframes = 1; |
|
954 |
|
|
955 |
inc_frame_num(pEnc); |
pEnc->bframenum_dx50bvop = -1; |
956 |
|
} |
957 |
|
|
958 |
if (pEnc->packed) { |
pEnc->flush_bframes = 1; |
959 |
|
|
960 |
|
if ((pEnc->global & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail > 0) { |
961 |
BitstreamPad(&bs); |
BitstreamPad(&bs); |
962 |
input_valid = 0; |
input_valid = 0; |
963 |
goto ipvop_loop; |
goto ipvop_loop; |
976 |
pEnc->bframenum_head, pEnc->bframenum_tail, |
pEnc->bframenum_head, pEnc->bframenum_tail, |
977 |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
978 |
|
|
979 |
|
if ((pEnc->global & XVID_GLOBAL_DEBUG)) { |
980 |
|
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "PVOP"); |
981 |
|
} |
982 |
|
|
983 |
FrameCodeP(pEnc, &bs, &bits, 1, 0); |
FrameCodeP(pEnc, &bs, &bits, 1, 0); |
984 |
pFrame->intra = 0; |
pFrame->intra = 0; |
985 |
pEnc->flush_bframes = 1; |
pEnc->flush_bframes = 1; |
986 |
|
|
987 |
inc_frame_num(pEnc); |
if ((pEnc->global & XVID_GLOBAL_PACKED)) { |
|
|
|
|
if (pEnc->packed) { |
|
988 |
BitstreamPad(&bs); |
BitstreamPad(&bs); |
989 |
input_valid = 0; |
input_valid = 0; |
990 |
goto ipvop_loop; |
goto ipvop_loop; |
999 |
pEnc->bframenum_head, pEnc->bframenum_tail, |
pEnc->bframenum_head, pEnc->bframenum_tail, |
1000 |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size); |
1001 |
|
|
1002 |
|
if ((pEnc->global & XVID_GLOBAL_DEBUG)) { |
1003 |
|
image_printf(&pEnc->current->image, pEnc->mbParam.edged_width, pEnc->mbParam.height, 5, 200, "BVOP"); |
1004 |
|
} |
1005 |
|
|
1006 |
if (pFrame->bquant < 1) { |
if (pFrame->bquant < 1) { |
1007 |
pEnc->current->quant = |
pEnc->current->quant = |
1008 |
((pEnc->reference->quant + |
((pEnc->reference->quant + |
1020 |
pFrame->intra = 0; |
pFrame->intra = 0; |
1021 |
pFrame->length = 0; |
pFrame->length = 0; |
1022 |
|
|
|
inc_frame_num(pEnc); |
|
|
|
|
1023 |
input_valid = 0; |
input_valid = 0; |
1024 |
goto bvop_loop; |
goto bvop_loop; |
1025 |
} |
} |
1335 |
tmp.y -= (tmp.y >= high) ? high * 2 : 0; |
tmp.y -= (tmp.y >= high) ? high * 2 : 0; |
1336 |
|
|
1337 |
get_pmvdata(pEnc->current->mbs, x, y, pEnc->mbParam.mb_width, |
get_pmvdata(pEnc->current->mbs, x, y, pEnc->mbParam.mb_width, |
1338 |
0, pred, dummy); |
0, pred, dummy, 0, 0); |
1339 |
|
|
1340 |
for (vec = 0; vec < 4; ++vec) { |
for (vec = 0; vec < 4; ++vec) { |
1341 |
pMB->mvs[vec].x = tmp.x; |
pMB->mvs[vec].x = tmp.x; |
1355 |
tmp.y -= (tmp.y >= high) ? high * 2 : 0; |
tmp.y -= (tmp.y >= high) ? high * 2 : 0; |
1356 |
|
|
1357 |
get_pmvdata(pEnc->current->mbs, x, y, |
get_pmvdata(pEnc->current->mbs, x, y, |
1358 |
pEnc->mbParam.mb_width, vec, pred, dummy); |
pEnc->mbParam.mb_width, vec, pred, dummy, 0, 0); |
1359 |
|
|
1360 |
pMB->mvs[vec].x = tmp.x; |
pMB->mvs[vec].x = tmp.x; |
1361 |
pMB->mvs[vec].y = tmp.y; |
pMB->mvs[vec].y = tmp.y; |
1492 |
BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); |
BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current); |
1493 |
#ifdef BFRAMES |
#ifdef BFRAMES |
1494 |
#define DIVX501B481P "DivX501b481p" |
#define DIVX501B481P "DivX501b481p" |
1495 |
if (pEnc->packed) { |
if ((pEnc->global & XVID_GLOBAL_PACKED)) { |
1496 |
BitstreamWriteUserData(bs, DIVX501B481P, strlen(DIVX501B481P)); |
BitstreamWriteUserData(bs, DIVX501B481P, strlen(DIVX501B481P)); |
1497 |
} |
} |
1498 |
#endif |
#endif |
1828 |
backward.x = mb->b_mvs[0].x; |
backward.x = mb->b_mvs[0].x; |
1829 |
backward.y = mb->b_mvs[0].y; |
backward.y = mb->b_mvs[0].y; |
1830 |
} |
} |
1831 |
// printf("[%i %i] M=%i CBP=%i MVX=%i MVY=%i %i,%i %i,%i\n", x, y, pMB->mode, pMB->cbp, pMB->mvs[0].x, bmb->pmvs[0].x, bmb->pmvs[0].y, forward.x, forward.y); |
// DPRINTF("%05i : [%i %i] M=%i CBP=%i MVS=%i,%i forward=%i,%i", pEnc->m_framenum, x, y, mb->mode, mb->cbp, mb->mvs[0].x, mb->mvs[0].y, forward.x, forward.y); |
1832 |
|
|
1833 |
start_timer(); |
start_timer(); |
1834 |
MBCodingBVOP(mb, qcoeff, frame->fcode, frame->bcode, bs, |
MBCodingBVOP(mb, qcoeff, frame->fcode, frame->bcode, bs, |