[Ffmpeg-devel] improved [PATCH] fix DV encoder VLC bit accounting
Dan Maas
dmaas
Thu Feb 23 00:40:58 CET 2006
Here is an updated patch. I believe this addresses all of Michael's
concerns. It only updates the single affected coefficient. The results
are identical to my previous patch, but the performance hit is more
like 1.5% now.
Unfortunately I can't send you Stuart's test video, but believe me,
without the fix there are very noticeable artifacts on some frames.
They are most visible on frames with a lot of high-frequency content.
Regards,
Dan
-------------- next part --------------
Index: libavcodec/dv.c
===================================================================
RCS file: /cvsroot/ffmpeg/ffmpeg/libavcodec/dv.c,v
retrieving revision 1.71
diff -u -p -u -r1.71 dv.c
--- libavcodec/dv.c 5 Feb 2006 13:35:16 -0000 1.71
+++ libavcodec/dv.c 22 Feb 2006 23:34:46 -0000
@@ -594,6 +594,7 @@ typedef struct EncBlockInfo {
int area_q[4];
int bit_size[4];
int prev[5];
+ int last_nonzero[4]; /* index of last nonzero AC coefficient within each area */
int cur_ac;
int cno;
int dct_mode;
@@ -658,6 +659,7 @@ static always_inline void dv_set_class_n
bi->mb[0] = blk[0];
for (area = 0; area < 4; area++) {
+ bi->last_nonzero[area] = -1;
bi->prev[area] = prev;
bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :)
for (i=mb_area_start[area]; i<mb_area_start[area+1]; i++) {
@@ -668,6 +670,7 @@ static always_inline void dv_set_class_n
bi->mb[i] = level= ABS(level)>>4;
if(level>max) max= level;
bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, level);
+ bi->last_nonzero[area] = i;
bi->next[prev]= i;
prev= i;
}
@@ -683,6 +686,7 @@ static always_inline void dv_set_class_n
prev=0;
i= bi->next[prev];
for (area = 0; area < 4; area++) {
+ bi->last_nonzero[area] = -1;
bi->prev[area] = prev;
bi->bit_size[area] = 1; // 4 areas 4 bits for EOB :)
for (; i<mb_area_start[area+1]; i= bi->next[i]) {
@@ -691,6 +695,7 @@ static always_inline void dv_set_class_n
if (bi->mb[i]) {
bi->bit_size[area] += dv_rl2vlc_size(i - prev - 1, bi->mb[i]);
bi->next[prev]= i;
+ bi->last_nonzero[area] = i;
prev= i;
}
}
@@ -740,8 +745,15 @@ static inline void dv_guess_qnos(EncBloc
qnos[i]--;
size[i] = 0;
for (j=0; j<6; j++, b++) {
+ /* index of area in which to force update of incoming run length */
+ int update_vlc = -1;
+ /* if update_vlc != -1, the start index of the old run */
+ int old_run = 0;
for (a=0; a<4; a++) {
if (b->area_q[a] != dv_quant_shifts[qnos[i] + dv_quant_offset[b->cno]][a]) {
+ /* Update quantizations and bit_size */
+ int last = b->last_nonzero[a];
+ b->last_nonzero[a] = -1;
b->bit_size[a] = 1; // 4 areas 4 bits for EOB :)
b->area_q[a]++;
prev= b->prev[a];
@@ -749,12 +761,35 @@ static inline void dv_guess_qnos(EncBloc
b->mb[k] >>= 1;
if (b->mb[k]) {
b->bit_size[a] += dv_rl2vlc_size(k - prev - 1, b->mb[k]);
+ b->last_nonzero[a] = k;
prev= k;
} else {
+ /* Coefficient became zero */
b->next[prev] = b->next[k];
+ if (k == last) {
+ /* Last nonzero coefficient has become zero */
+ /* Set flag to update bit_size of following area */
+ update_vlc = a+1;
+ old_run = k;
+ }
}
}
b->prev[a+1]= prev;
+ } else if (update_vlc == a) {
+ /* Update bit_size of following area */
+ /* We must do this since RLE code lengths depend on run length */
+ prev = b->prev[a];
+ k = b->next[prev];
+ if (k < mb_area_start[a+1]) {
+ /* Adjust bit_size to account for new incoming run length */
+ b->bit_size[a] += dv_rl2vlc_size(k - prev - 1, b->mb[k]) -
+ dv_rl2vlc_size(k - old_run - 1, b->mb[k]);
+ update_vlc = -1;
+ } else {
+ /* This area is all zero, set flag for next area */
+ update_vlc = a+1;
+ b->prev[a+1] = prev;
+ }
}
size[i] += b->bit_size[a];
}
More information about the ffmpeg-devel
mailing list