[XviD-devel] Data partitioning for encoder
sigdrak
sigdrak at free.fr
Mon Apr 18 20:44:32 CEST 2005
Hello,
the attached patch should provide data partitioning abilities to the
encoder. For reasons stated later in the mail, this patch may not apply
cleanly - I haven't investigated much what gets broken otherwise. I
tested IP...P sequences using mplayer. B frames should not be affected
by data partitioning, per the standard. I could have tested with MoMuSys
but I prefered saving myself the trouble and submit this patch right away.
For this I introduced:
- 2 additional bitstream in the encoder creator and frame structure
- 2 additional flags for signaling data partitioning (at the encoder
level and the frame level)
- a function to concatenate bitstreams.
- a modification of functions in mbcoding.c to write in the proper
bitstreams
For info, the bitstream should look (from my recollection of my code)
like this with data partitioning:
- I MB: (mcbpc,dquant,interlace,dc) DC_MARKER (ac_pred_flag,ac)
- P intra MB: (mcbpc) DC_MARKER (dquant,interlace,dc) (ac_pred_flag, ac)
- P inter MB: (mcbpc,mc_sel,MV) MOTION_MARKER (cbpy,dquant,interlace)
(coeffs)
I also wrote functions which are not used yet (or ever) and which I hope
are self-explaining names:
- BitStreamWriteStartOfVideoPacket
- BitstreamWriteGroupOfVopHeader
- BitstreamWriteEndOfSequence
About the two last: I suspect that AVI or proper frame cutting is
responsible for them not being used, and a new VOL is used instead of a GOV.
Globally, I had trouble with indentation: code uses tabs and not spaces
(this is left for trolling on other occasions). So, I hope it won't
break up too many things. Otherwise, I'd be interested if someone has
set up a XVID coding style profile for vi or emacs famillies (see
indentation remark).
I have decoder-side pending code, but unfortunately, it is merged with
work on video packetization. I'd prefer not to go through the trouble of
making a proper patch for the decoder, as data partitioning and video
packetiztion get deeply tied at some point. Therefore, I'd prefer to see
the present patch merged first.
By the way, my packetization seems to work on both encoder and decoder
sides, but I haven't tested it yet on B-frames. I'm opting for a packet
size parameter, as the profiles rather state this limit over any other.
Packetization or data partitioning or normal coding all work separately,
but packetization+data partitioning still fails.
A proper design however is needed:
- bumping API, bitstream and any other version
- plugin interfaces for controlling the packetization process
- proper encoder/decoder interfaces based on video packets instead of
full-frame en/decoding
- a plugin specialized in enforcing the video packet sizes whenever
video packetization is used and a profile is selected
Regards,
sigdrak.
-------------- next part --------------
Index: src/encoder.c
===================================================================
RCS file: /xvid/xvidcore/src/encoder.c,v
retrieving revision 1.117
diff -B -b -d -u -r1.117 encoder.c
--- src/encoder.c 27 Mar 2005 03:59:42 -0000 1.117
+++ src/encoder.c 9 Apr 2005 18:22:04 -0000
@@ -54,10 +54,14 @@
****************************************************************************/
static int FrameCodeI(Encoder * pEnc,
- Bitstream * bs);
+ Bitstream * bs,
+ void *buff2,
+ void *buf_tex);
static int FrameCodeP(Encoder * pEnc,
- Bitstream * bs);
+ Bitstream * bs,
+ void *buff2,
+ void *buf_tex);
static void FrameCodeB(Encoder * pEnc,
FRAMEINFO * frame,
@@ -1102,7 +1106,7 @@
pEnc->queue_head, pEnc->queue_tail, pEnc->queue_size);
pEnc->mbParam.frame_drop_ratio = -1; /* it must be a coded vop */
- FrameCodeP(pEnc, &bs);
+ FrameCodeP(pEnc, &bs, xFrame->secondary_bitstream, xFrame->texture_bitstream);
if ((pEnc->mbParam.global_flags & XVID_GLOBAL_PACKED) && pEnc->bframenum_tail==0) {
@@ -1329,7 +1333,7 @@
pEnc->mbParam.edged_width, pEnc->mbParam.height);
}
- FrameCodeI(pEnc, &bs);
+ FrameCodeI(pEnc, &bs, xFrame->secondary_bitstream, xFrame->texture_bitstream);
xFrame->out_flags |= XVID_KEYFRAME;
/* %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
@@ -1351,7 +1355,7 @@
pEnc->mbParam.edged_width, pEnc->mbParam.height);
}
- if ( FrameCodeP(pEnc, &bs) == 0 ) {
+ if ( FrameCodeP(pEnc, &bs, xFrame->secondary_bitstream, xFrame->texture_bitstream) == 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;
@@ -1435,8 +1439,13 @@
static int
FrameCodeI(Encoder * pEnc,
- Bitstream * bs)
+ Bitstream * bs,
+ void *buf2,
+ void *buf_tex)
{
+ Bitstream bs2_instance, *bs2 = NULL; /* Second part of headers */
+ Bitstream bs_tex_instance, *bs_tex = NULL; /* Texture bitstream */
+
int bits = BitstreamPos(bs);
int mb_width = pEnc->mbParam.mb_width;
int mb_height = pEnc->mbParam.mb_height;
@@ -1450,11 +1459,45 @@
pEnc->current->rounding_type = pEnc->mbParam.m_rounding_type;
pEnc->current->coding_type = I_VOP;
+ /* TODO: allow dynamic setting of the data partitioning */
+ if (pEnc->mbParam.global_flags & XVID_GLOBAL_DATA_PARTITIONING) {
+ pEnc->current->vop_flags |= XVID_VOP_DATA_PARTITIONED;
+ }
+
+ /* Set it for data paritioning */
+ if (pEnc->current->vop_flags & XVID_VOP_DATA_PARTITIONED)
+ {
+ /* bs2 uses secondary_bitstream, so the application could use
+ * that to split back the frame into packets.
+ * TODO: Implement a callback for GOB/VideoPacket
+ */
+ bs2 = &bs2_instance;
+ bs_tex = &bs_tex_instance;
+ BitstreamInit(bs2, buf2, 0);
+ BitstreamInit(bs_tex, buf_tex, 0);
+ BitstreamPutBits(bs2, DC_MARKER, 19);
+ DPRINTF(XVID_DEBUG_HEADER, "Data partitioned I frame\n");
+ }
+ else
+ {
+ bs2 = bs;
+ bs_tex = bs;
+ }
+
call_plugins(pEnc, pEnc->current, NULL, XVID_PLG_FRAME, NULL, NULL, NULL);
SetMacroblockQuants(&pEnc->mbParam, pEnc->current);
+#if 1
BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current);
+#else
+ /* Probably don't cope well with AVI frame cuts */
+ if (pEnc->m_framenum == 0)
+ BitstreamWriteVolHeader(bs, &pEnc->mbParam, pEnc->current);
+ else
+ BitstreamWriteGroupOfVopHeader(bs, &pEnc->mbParam,
+ pEnc->global_flags&XVID_GLOBAL_CLOSED_GOP);
+#endif
set_timecodes(pEnc->current,pEnc->reference,pEnc->mbParam.fbase);
@@ -1481,10 +1524,16 @@
stop_prediction_timer();
start_timer();
- MBCoding(pEnc->current, pMB, qcoeff, bs, &pEnc->current->sStat);
+ MBCoding(pEnc->current, pMB, qcoeff, bs, bs2, bs_tex, &pEnc->current->sStat);
stop_coding_timer();
}
+ if (pEnc->current->vop_flags & XVID_VOP_DATA_PARTITIONED) {
+ /* The resynch marker isn't byte-aligned !! */
+ BitstreamsConcatenate(bs, bs2, 0);
+ BitstreamsConcatenate(bs, bs_tex, 0);
+ }
+
emms();
BitstreamPadAlways(bs); /* next_start_code() at the end of VideoObjectPlane() */
@@ -1529,8 +1578,13 @@
/* FrameCodeP also handles S(GMC)-VOPs */
static int
FrameCodeP(Encoder * pEnc,
- Bitstream * bs)
+ Bitstream * bs,
+ void *buf2,
+ void *buf_tex)
{
+ Bitstream bs2_instance, *bs2; /* Second part of headers */
+ Bitstream bs_tex_instance, *bs_tex; /* Texture bitstream */
+
int bits = BitstreamPos(bs);
DECLARE_ALIGNED_MATRIX(dct_codes, 6, 64, int16_t, CACHE_LINE);
@@ -1546,6 +1600,31 @@
IMAGE *pRef = &reference->image;
+ /* TODO: allow dynamic setting of the data partitioning */
+ if (pEnc->mbParam.global_flags & XVID_GLOBAL_DATA_PARTITIONING) {
+ pEnc->current->vop_flags |= XVID_VOP_DATA_PARTITIONED;
+ }
+
+ /* Set it for data paritioning */
+ if (pEnc->current->vop_flags & XVID_VOP_DATA_PARTITIONED)
+ {
+ /* bs2 uses secondary_bitstream, so the application could use
+ * that to split back the frame into packets.
+ * TODO: Implement a callback for GOB/VideoPacket
+ */
+ bs2 = &bs2_instance;
+ bs_tex = &bs_tex_instance;
+ BitstreamInit(bs2, buf2, 0);
+ BitstreamInit(bs_tex, buf_tex, 0);
+ BitstreamPutBits(bs2, MOTION_MARKER, 17);
+ DPRINTF(XVID_DEBUG_HEADER, "Data partitioned P frame\n");
+ }
+ else
+ {
+ bs2 = bs;
+ bs_tex = bs;
+ }
+
if (!reference->is_edged) {
start_timer();
image_setedges(pRef, pParam->edged_width, pParam->edged_height,
@@ -1658,7 +1737,7 @@
current->sStat.kblks++;
- MBCoding(current, pMB, qcoeff, bs, ¤t->sStat);
+ MBCoding(current, pMB, qcoeff, bs, bs2, bs_tex, ¤t->sStat);
stop_coding_timer();
continue;
}
@@ -1748,7 +1827,7 @@
}
/* ordinary case: normal coded INTER/INTER4V block */
- MBCoding(current, pMB, qcoeff, bs, &pEnc->current->sStat);
+ MBCoding(current, pMB, qcoeff, bs, bs2, bs_tex, &pEnc->current->sStat);
stop_coding_timer();
}
}
@@ -1767,7 +1846,8 @@
current->sStat.kblks = current->sStat.mblks = 0;
current->sStat.ublks = mb_width * mb_height;
- BitstreamReset(bs);
+ /* XXX: what if the bitstreams are used for packetization */
+ BitstreamReset(bs); /* No need to reset other bitstreams */
set_timecodes(current,reference,pParam->fbase);
BitstreamWriteVopHeader(bs, &pEnc->mbParam, current, 0, current->mbs[0].quant);
@@ -1796,6 +1876,12 @@
image_swap(&pEnc->vInterHV, &pEnc->f_refhv);
}
+ if (pEnc->current->vop_flags & XVID_VOP_DATA_PARTITIONED) {
+ /* The resynch marker isn't byte-aligned !! */
+ BitstreamsConcatenate(bs, bs2, 0);
+ BitstreamsConcatenate(bs, bs_tex, 0);
+ }
+
/* XXX: debug
{
char s[100];
Index: src/xvid.h
===================================================================
RCS file: /xvid/xvidcore/src/xvid.h,v
retrieving revision 1.50
diff -B -b -d -u -r1.50 xvid.h
--- src/xvid.h 4 Apr 2005 23:49:37 -0000 1.50
+++ src/xvid.h 9 Apr 2005 18:22:04 -0000
@@ -595,6 +595,7 @@
#endif
#define XVID_GLOBAL_DIVX5_USERDATA (1<<5) /* write divx5 userdata string
this is implied if XVID_GLOBAL_PACKED is set */
+#define XVID_GLOBAL_DATA_PARTITIONING (1<<6) /* Use data partitioning */
/*----------------------------------------------------------------------------
* "VOL" flags
@@ -630,6 +631,7 @@
#define XVID_VOP_MODEDECISION_RD (1<< 8) /* enable DCT-ME and use it for mode decision */
#define XVID_VOP_FAST_MODEDECISION_RD (1<<12) /* use simplified R-D mode decision */
#define XVID_VOP_RD_BVOP (1<<13) /* enable rate-distortion mode decision in b-frames */
+#define XVID_VOP_DATA_PARTITIONED (1<<14) /* per-frame data partitioning signal */
/* Only valid for vol_flags|=XVID_VOL_INTERLACING */
#define XVID_VOP_TOPFIELDFIRST (1<< 9) /* set top-field-first flag */
@@ -775,11 +777,17 @@
int bframe_threshold;
void *bitstream; /* [in:opt] bitstream ptr (written to)*/
- int length; /* [in:opt] bitstream length (bytes) */
+ void *secondary_bitstream; /* [in:opt] secondary bitstream ptr (written to)*/
+ void *texture_bitstream; /* [in:opt] texture bitstream ptr (written to)*/
+ int length; /* [in:opt] total bitstream length (bytes) */
int out_flags; /* [out] bitstream output flags */
} xvid_enc_frame_t;
+/* Markers */
+#define DC_MARKER 0x6B001
+#define MOTION_MARKER 0x1F001
+
#ifdef __cplusplus
}
#endif
Index: src/bitstream/bitstream.c
===================================================================
RCS file: /xvid/xvidcore/src/bitstream/bitstream.c,v
retrieving revision 1.49
diff -B -b -d -u -r1.49 bitstream.c
--- src/bitstream/bitstream.c 27 Mar 2005 03:59:42 -0000 1.49
+++ src/bitstream/bitstream.c 9 Apr 2005 18:22:04 -0000
@@ -702,7 +702,8 @@
BitstreamSkip(bs, 1); /* resync_marker_disable */
- if (BitstreamGetBit(bs)) /* data_partitioned */
+ dec->data_partitioning = BitstreamGetBit(bs);
+ if (dec->data_partitioning) /* data_partitioned */
{
DPRINTF(XVID_DEBUG_ERROR, "data_partitioned not supported\n");
BitstreamSkip(bs, 1); /* reversible_vlc */
@@ -1239,7 +1240,16 @@
BitstreamPutBit(bs, 1); /* complexity_estimation_disable */
BitstreamPutBit(bs, 1); /* resync_marker_disable */
- BitstreamPutBit(bs, 0); /* data_partitioned */
+
+ if (frame->vop_flags & XVID_VOP_DATA_PARTITIONED) {
+ BitstreamPutBit(bs, 1); /* data_partitioned */
+ BitstreamPutBit(bs, 0); /* not use_reversible_vlc */
+ DPRINTF(XVID_DEBUG_HEADER, "Using data partitioning\n");
+ }
+ else
+ {
+ BitstreamPutBit(bs, 0); /* not data_partitioned */
+ }
if (vol_ver_id != 1) {
BitstreamPutBit(bs, 0); /* newpred_enable */
@@ -1271,6 +1281,31 @@
}
}
+/*
+ write group of vops header
+ XXX: we should get FRAMEINFO.seconds ...
+*/
+void
+BitstreamWriteGroupOfVopHeader(Bitstream * const bs,
+ const MBParam * pParam,
+ uint32_t is_closed_gov)
+{
+ int64_t time = (pParam->m_stamp + (pParam->fbase/2)) / pParam->fbase;
+ int hours, minutes, seconds;
+
+ /* compute time_code */
+ seconds = time % 60; time /= 60;
+ minutes = time % 60; time /= 60;
+ hours = time % 24; /* don't overflow */
+
+ BitstreamPutBits(bs, GRPOFVOP_START_CODE, 32);
+ BitstreamPutBits(bs, hours, 5);
+ BitstreamPutBits(bs, minutes, 6);
+ BitstreamPutBit(bs, 1);
+ BitstreamPutBits(bs, seconds, 6);
+ BitstreamPutBits(bs, is_closed_gov, 1);
+ BitstreamPutBits(bs, 0, 1); /* broken_link */
+}
/*
write vop header
@@ -1401,3 +1436,41 @@
}
}
+
+void
+BitstreamWriteEndOfSequence(Bitstream * const bs)
+{
+ BitstreamPad(bs);
+ BitstreamPutBits(bs, VISOBJSEQ_STOP_CODE, 32);
+}
+
+void BitStreamWriteStartOfVideoPacket(Bitstream * const bs,
+ const MBParam * pParam,
+ const FRAMEINFO * const frame,
+ unsigned int quant,
+ uint32_t macroblock_number)
+{
+ int rm_length = 0; /* resynch marker length */
+ uint32_t i;
+
+ BitstreamPad(bs);
+
+ /* Set total resynch marker length ('0's followed by '1') */
+ switch(frame->coding_type) {
+ case I_VOP: rm_length = 17; break;
+ case P_VOP:
+ case S_VOP: rm_length = 16+frame->fcode; break;
+ case B_VOP: rm_length = MAX(18, 17+frame->fcode); break;
+ default: DPRINTF(XVID_DEBUG_HEADER, "type=%i", quant);
+ }
+ /* Write it */
+ BitstreamPutBits(bs, 1, rm_length);
+
+ /* Write macroblock number */
+ BitstreamPutBits(bs, macroblock_number,
+ log2bin(pParam->mb_width * pParam->mb_height - 1));
+
+
+ BitstreamPutBits(bs, quant, 5); /* quant_scale */
+ BitstreamPutBits(bs, 0, 1); /* No HEC */
+};
Index: src/bitstream/bitstream.h
===================================================================
RCS file: /xvid/xvidcore/src/bitstream/bitstream.h,v
retrieving revision 1.20
diff -B -b -d -u -r1.20 bitstream.h
--- src/bitstream/bitstream.h 5 Dec 2004 13:56:13 -0000 1.20
+++ src/bitstream/bitstream.h 9 Apr 2005 18:22:04 -0000
@@ -149,6 +149,13 @@
uint8_t * data,
const int length);
+void BitstreamWriteEndOfSequence(Bitstream * const bs);
+void BitStreamWriteStartOfVideoPacket(Bitstream * const bs,
+ const MBParam * pParam,
+ const FRAMEINFO * const frame,
+ unsigned int quant,
+ uint32_t macroblock_number);
+
/* initialise bitstream structure */
static void __inline
@@ -452,4 +459,44 @@
BitstreamPutBits(bs, stuffing_codes[bits - 1], bits);
}
+
+/*
+ * Concatenate 2 bitstreams without padding
+ */
+static void __inline
+BitstreamsConcatenate(Bitstream * bso, Bitstream * const bsi, int padd)
+{
+ uint32_t dwords;
+ uint32_t b;
+ int i;
+
+ switch (padd) {
+ case 1: BitstreamPad(bso); break;
+ case 2: BitstreamPadAlways(bso); break;
+ default: break;
+ }
+
+ /* Get size */
+ dwords = ((ptr_t)bsi->tail - (ptr_t)bsi->start)>>2;
+
+ /* Loop on dwords */
+ for (i=0; i<dwords; i++)
+ {
+#ifndef ARCH_IS_BIG_ENDIAN
+ b = bsi->start[i];
+ BSWAP(b);
+ BitstreamPutBits(bso, b, 32);
+#else
+ BitstreamPutBits(bso, bsi->start[i], 32);
+#endif
+ }
+
+ /* XXX: how to flush the latest buf ? */
+ if (bsi->pos) {
+ b = bsi->buf >> (32 - bsi->pos);
+ /* (bsi->buf & (0xffffffff >> bsi->pos)) >> (32 - bsi->pos); */
+ BitstreamPutBits(bso, b, bsi->pos);
+ }
+}
+
#endif /* _BITSTREAM_H_ */
Index: src/bitstream/mbcoding.c
===================================================================
RCS file: /xvid/xvidcore/src/bitstream/mbcoding.c,v
retrieving revision 1.51
diff -B -b -d -u -r1.51 mbcoding.c
--- src/bitstream/mbcoding.c 4 Apr 2005 23:49:37 -0000 1.51
+++ src/bitstream/mbcoding.c 9 Apr 2005 18:22:04 -0000
@@ -63,7 +63,7 @@
int bs_get_spritetrajectory(Bitstream * bs)
{
int i;
- for (i = 0; i < 12; i++)
+ for (i = 0; i < 15; i++)
{
if (BitstreamShowBits(bs, sprite_trajectory_len[i].len) == sprite_trajectory_len[i].code)
{
@@ -462,14 +462,17 @@
const MACROBLOCK * pMB,
int16_t qcoeff[6 * 64],
Bitstream * bs,
+ Bitstream * bs2,
+ Bitstream * bs_tex,
Statistics * pStat)
{
uint32_t i, mcbpc, cbpy, bits;
+ Bitstream * bs_local;
cbpy = pMB->cbp >> 2;
- /* write mcbpc */
+ /* write mcbpc - first bs */
if (frame->coding_type == I_VOP) {
mcbpc = ((pMB->mode >> 1) & 3) | ((pMB->cbp & 3) << 2);
BitstreamPutBits(bs, mcbpc_intra_tab[mcbpc].code,
@@ -480,42 +483,46 @@
mcbpc_inter_tab[mcbpc].len);
}
- /* ac prediction flag */
+ /* ac prediction flag - second bs */
if (pMB->acpred_directions[0])
- BitstreamPutBits(bs, 1, 1);
+ BitstreamPutBits(bs2, 1, 1);
else
- BitstreamPutBits(bs, 0, 1);
+ BitstreamPutBits(bs2, 0, 1);
- /* write cbpy */
- BitstreamPutBits(bs, xvid_cbpy_tab[cbpy].code, xvid_cbpy_tab[cbpy].len);
+ /* write cbpy - second bs */
+ BitstreamPutBits(bs2, xvid_cbpy_tab[cbpy].code, xvid_cbpy_tab[cbpy].len);
- /* write dquant */
+ /* write dquant - first bs for I_VOP, second otherwise */
+ bs_local = (frame->coding_type == I_VOP) ? bs : bs2;
if (pMB->mode == MODE_INTRA_Q)
- BitstreamPutBits(bs, DQ_VALUE2INDEX(pMB->dquant), 2);
+ BitstreamPutBits(bs_local, DQ_VALUE2INDEX(pMB->dquant), 2);
- /* write interlacing */
+ /* write interlacing - same */
if (frame->vol_flags & XVID_VOL_INTERLACING) {
- BitstreamPutBit(bs, pMB->field_dct);
+ BitstreamPutBit(bs_local, pMB->field_dct);
}
/* code block coeffs */
for (i = 0; i < 6; i++) {
+ /* DC goes to first bs for I-VOP, second otherwise */
if (i < 4)
- BitstreamPutBits(bs, dcy_tab[qcoeff[i * 64 + 0] + 255].code,
+ BitstreamPutBits(bs_local,
+ dcy_tab[qcoeff[i * 64 + 0] + 255].code,
dcy_tab[qcoeff[i * 64 + 0] + 255].len);
else
- BitstreamPutBits(bs, dcc_tab[qcoeff[i * 64 + 0] + 255].code,
+ BitstreamPutBits(bs_local,
+ dcc_tab[qcoeff[i * 64 + 0] + 255].code,
dcc_tab[qcoeff[i * 64 + 0] + 255].len);
+ /* AC goes to texture bs */
if (pMB->cbp & (1 << (5 - i))) {
const uint16_t *scan_table =
frame->vop_flags & XVID_VOP_ALTERNATESCAN ?
scan_tables[2] : scan_tables[pMB->acpred_directions[i]];
+ bits = BitstreamPos(bs_tex);
- bits = BitstreamPos(bs);
-
- CodeCoeffIntra(bs, &qcoeff[i * 64], scan_table);
+ CodeCoeffIntra(bs_tex, &qcoeff[i * 64], scan_table);
- bits = BitstreamPos(bs) - bits;
+ bits = BitstreamPos(bs_tex) - bits;
pStat->iTextBits += bits;
}
}
@@ -528,6 +535,8 @@
const MACROBLOCK * pMB,
int16_t qcoeff[6 * 64],
Bitstream * bs,
+ Bitstream * bs2,
+ Bitstream * bs_tex,
Statistics * pStat)
{
@@ -537,61 +546,62 @@
mcbpc = (pMB->mode & 7) | ((pMB->cbp & 3) << 3);
cbpy = 15 - (pMB->cbp >> 2);
- /* write mcbpc */
+ /* write mcbpc - first bs */
BitstreamPutBits(bs, mcbpc_inter_tab[mcbpc].code,
mcbpc_inter_tab[mcbpc].len);
+ /* XXX: Is it its actual place ? */
if ( (frame->coding_type == S_VOP) && (pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q) )
BitstreamPutBit(bs, pMB->mcsel); /* mcsel: '0'=local motion, '1'=GMC */
- /* write cbpy */
- BitstreamPutBits(bs, xvid_cbpy_tab[cbpy].code, xvid_cbpy_tab[cbpy].len);
+ /* write cbpy - second bs */
+ BitstreamPutBits(bs2, xvid_cbpy_tab[cbpy].code, xvid_cbpy_tab[cbpy].len);
- /* write dquant */
+ /* write dquant - second bs */
if (pMB->mode == MODE_INTER_Q)
- BitstreamPutBits(bs, DQ_VALUE2INDEX(pMB->dquant), 2);
+ BitstreamPutBits(bs2, DQ_VALUE2INDEX(pMB->dquant), 2);
- /* interlacing */
+ /* interlacing - second bs */
if (frame->vol_flags & XVID_VOL_INTERLACING) {
if (pMB->cbp) {
- BitstreamPutBit(bs, pMB->field_dct);
+ BitstreamPutBit(bs2, pMB->field_dct);
DPRINTF(XVID_DEBUG_MB,"codep: field_dct: %i\n", pMB->field_dct);
}
/* if inter block, write field ME flag */
if ((pMB->mode == MODE_INTER || pMB->mode == MODE_INTER_Q) && (pMB->mcsel == 0)) {
- BitstreamPutBit(bs, 0 /*pMB->field_pred*/); /* not implemented yet */
+ BitstreamPutBit(bs2, 0 /*pMB->field_pred*/); /* not implemented yet */
DPRINTF(XVID_DEBUG_MB,"codep: field_pred: %i\n", pMB->field_pred);
/* write field prediction references */
#if 0 /* Remove the #if once field_pred is supported */
if (pMB->field_pred) {
- BitstreamPutBit(bs, pMB->field_for_top);
- BitstreamPutBit(bs, pMB->field_for_bot);
+ BitstreamPutBit(bs2, pMB->field_for_top);
+ BitstreamPutBit(bs2, pMB->field_for_bot);
}
#endif
}
}
- /* code motion vector(s) if motion is local */
+ /* code motion vector(s) if motion is local - first bs */
if (!pMB->mcsel)
for (i = 0; i < (pMB->mode == MODE_INTER4V ? 4 : 1); i++) {
CodeVector(bs, pMB->pmvs[i].x, frame->fcode);
CodeVector(bs, pMB->pmvs[i].y, frame->fcode);
}
- bits = BitstreamPos(bs);
+ /* code block coeffs - texture bs */
+ bits = BitstreamPos(bs_tex);
- /* code block coeffs */
for (i = 0; i < 6; i++)
if (pMB->cbp & (1 << (5 - i))) {
const uint16_t *scan_table =
frame->vop_flags & XVID_VOP_ALTERNATESCAN ?
scan_tables[2] : scan_tables[0];
- CodeCoeffInter(bs, &qcoeff[i * 64], scan_table);
+ CodeCoeffInter(bs_tex, &qcoeff[i * 64], scan_table);
}
- bits = BitstreamPos(bs) - bits;
+ bits = BitstreamPos(bs_tex) - bits;
pStat->iTextBits += bits;
}
@@ -601,10 +611,12 @@
MACROBLOCK * pMB,
int16_t qcoeff[6 * 64],
Bitstream * bs,
+ Bitstream * bs2,
+ Bitstream * bs_tex,
Statistics * pStat)
{
if (frame->coding_type != I_VOP)
- BitstreamPutBit(bs, 0); /* not_coded */
+ BitstreamPutBit(bs, 0); /* not_coded = 0 */
if (frame->vop_flags & XVID_VOP_GREYSCALE) {
pMB->cbp &= 0x3C; /* keep only bits 5-2 */
@@ -613,9 +625,9 @@
}
if (pMB->mode == MODE_INTRA || pMB->mode == MODE_INTRA_Q)
- CodeBlockIntra(frame, pMB, qcoeff, bs, pStat);
+ CodeBlockIntra(frame, pMB, qcoeff, bs, bs2, bs_tex, pStat);
else
- CodeBlockInter(frame, pMB, qcoeff, bs, pStat);
+ CodeBlockInter(frame, pMB, qcoeff, bs, bs2, bs_tex, pStat);
}
Index: src/utils/mbfunctions.h
===================================================================
RCS file: /xvid/xvidcore/src/utils/mbfunctions.h,v
retrieving revision 1.20
diff -B -b -d -u -r1.20 mbfunctions.h
--- src/utils/mbfunctions.h 5 Jan 2005 23:02:15 -0000 1.20
+++ src/utils/mbfunctions.h 9 Apr 2005 18:22:05 -0000
@@ -84,6 +84,8 @@
MACROBLOCK * pMB, /* <-- Info of the MB to be coded */
int16_t qcoeff[6 * 64], /* <-- the quantized DCT coefficients */
Bitstream * bs, /* <-> the bitstream */
+ Bitstream * bs2, /* <-> the secondary bitstream with data partitioning */
+ Bitstream * bs_tex, /* <-> the texture bitstream with data partitioning */
Statistics * pStat); /* <-> statistical data collected for current frame */
#endif
More information about the XviD-devel
mailing list