aboutsummaryrefslogtreecommitdiffstats
path: root/libavcodec
diff options
context:
space:
mode:
authorMike Melanson <mike@multimedia.cx>2009-12-02 02:30:15 +0000
committerMike Melanson <mike@multimedia.cx>2009-12-02 02:30:15 +0000
commit098523eb28df3a1cf4bddca088d80d5cbd2b9a1f (patch)
tree9397b7a245f2492f4da43215c8212ea90caa1526 /libavcodec
parent5dad039bf760b6bad30186cd18526ebffc7fc291 (diff)
downloadffmpeg-098523eb28df3a1cf4bddca088d80d5cbd2b9a1f.tar.gz
Use a list to track which fragments coded in this frame still have
outstanding coefficients yet to be decoded from the bitstream. Once a fragment reaches end-of-block, remove it from this new list. This change makes the VP3/Theora entropy decode process dramatically faster due to not having to iterate incessantly over fragments which have already been fully decoded. Originally committed as revision 20698 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec')
-rw-r--r--libavcodec/vp3.c91
1 files changed, 70 insertions, 21 deletions
diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
index 60b84f0b5f..292f01045e 100644
--- a/libavcodec/vp3.c
+++ b/libavcodec/vp3.c
@@ -179,6 +179,14 @@ typedef struct Vp3DecodeContext {
int coded_fragment_list_index;
int pixel_addresses_initialized;
+ /* track which fragments have already been decoded; called 'fast'
+ * because this data structure avoids having to iterate through every
+ * fragment in coded_fragment_list; once a fragment has been fully
+ * decoded, it is removed from this list */
+ int *fast_fragment_list;
+ int fragment_list_y_head;
+ int fragment_list_c_head;
+
VLC dc_vlc[16];
VLC ac_vlc_1[16];
VLC ac_vlc_2[16];
@@ -723,6 +731,25 @@ static int unpack_superblocks(Vp3DecodeContext *s, GetBitContext *gb)
/* end the list of coded C fragments */
s->last_coded_c_fragment = s->coded_fragment_list_index - 1;
+ for (i = 0; i < s->fragment_count - 1; i++) {
+ s->fast_fragment_list[i] = i + 1;
+ }
+ s->fast_fragment_list[s->fragment_count - 1] = -1;
+
+ if (s->last_coded_y_fragment == -1)
+ s->fragment_list_y_head = -1;
+ else {
+ s->fragment_list_y_head = s->first_coded_y_fragment;
+ s->fast_fragment_list[s->last_coded_y_fragment] = -1;
+ }
+
+ if (s->last_coded_c_fragment == -1)
+ s->fragment_list_c_head = -1;
+ else {
+ s->fragment_list_c_head = s->first_coded_c_fragment;
+ s->fast_fragment_list[s->last_coded_c_fragment] = -1;
+ }
+
return 0;
}
@@ -1029,7 +1056,7 @@ static int unpack_block_qpis(Vp3DecodeContext *s, GetBitContext *gb)
*/
static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
VLC *table, int coeff_index,
- int first_fragment, int last_fragment,
+ int y_plane,
int eob_run)
{
int i;
@@ -1038,6 +1065,10 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
DCTELEM coeff = 0;
Vp3Fragment *fragment;
int bits_to_get;
+ int next_fragment;
+ int previous_fragment;
+ int fragment_num;
+ int *list_head;
/* local references to structure members to avoid repeated deferences */
uint8_t *perm= s->scantable.permutated;
@@ -1045,20 +1076,26 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
Vp3Fragment *all_fragments = s->all_fragments;
uint8_t *coeff_counts = s->coeff_counts;
VLC_TYPE (*vlc_table)[2] = table->table;
+ int *fast_fragment_list = s->fast_fragment_list;
- if ((first_fragment >= s->fragment_count) ||
- (last_fragment >= s->fragment_count)) {
-
- av_log(s->avctx, AV_LOG_ERROR, " vp3:unpack_vlcs(): bad fragment number (%d -> %d ?)\n",
- first_fragment, last_fragment);
- return 0;
+ if (y_plane) {
+ next_fragment = s->fragment_list_y_head;
+ list_head = &s->fragment_list_y_head;
+ } else {
+ next_fragment = s->fragment_list_c_head;
+ list_head = &s->fragment_list_c_head;
}
- for (i = first_fragment; i <= last_fragment; i++) {
- int fragment_num = coded_fragment_list[i];
+ i = next_fragment;
+ previous_fragment = -1; /* this indicates that the previous fragment is actually the list head */
+ while (i != -1) {
+ fragment_num = coded_fragment_list[i];
- if (coeff_counts[fragment_num] > coeff_index)
+ if (coeff_counts[fragment_num] > coeff_index) {
+ previous_fragment = i;
+ i = fast_fragment_list[i];
continue;
+ }
fragment = &all_fragments[fragment_num];
if (!eob_run) {
@@ -1091,10 +1128,20 @@ static int unpack_vlcs(Vp3DecodeContext *s, GetBitContext *gb,
s->next_coeff->next=NULL;
fragment->next_coeff= s->next_coeff++;
}
+ /* previous fragment is now this fragment */
+ previous_fragment = i;
} else {
coeff_counts[fragment_num] |= 128;
eob_run--;
+ /* remove this fragment from the list */
+ if (previous_fragment != -1)
+ fast_fragment_list[previous_fragment] = fast_fragment_list[i];
+ else
+ *list_head = fast_fragment_list[i];
+ /* previous fragment remains unchanged */
}
+
+ i = fast_fragment_list[i];
}
return eob_run;
@@ -1123,14 +1170,14 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb)
/* unpack the Y plane DC coefficients */
residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_y_table], 0,
- s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+ 1, residual_eob_run);
/* reverse prediction of the Y-plane DC coefficients */
reverse_dc_prediction(s, 0, s->fragment_width, s->fragment_height);
/* unpack the C plane DC coefficients */
residual_eob_run = unpack_vlcs(s, gb, &s->dc_vlc[dc_c_table], 0,
- s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+ 0, residual_eob_run);
/* reverse prediction of the C-plane DC coefficients */
if (!(s->avctx->flags & CODEC_FLAG_GRAY))
@@ -1148,37 +1195,37 @@ static int unpack_dct_coeffs(Vp3DecodeContext *s, GetBitContext *gb)
/* unpack the group 1 AC coefficients (coeffs 1-5) */
for (i = 1; i <= 5; i++) {
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_1[ac_y_table], i,
- s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+ 1, residual_eob_run);
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_1[ac_c_table], i,
- s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+ 0, residual_eob_run);
}
/* unpack the group 2 AC coefficients (coeffs 6-14) */
for (i = 6; i <= 14; i++) {
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_2[ac_y_table], i,
- s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+ 1, residual_eob_run);
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_2[ac_c_table], i,
- s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+ 0, residual_eob_run);
}
/* unpack the group 3 AC coefficients (coeffs 15-27) */
for (i = 15; i <= 27; i++) {
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_3[ac_y_table], i,
- s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+ 1, residual_eob_run);
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_3[ac_c_table], i,
- s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+ 0, residual_eob_run);
}
/* unpack the group 4 AC coefficients (coeffs 28-63) */
for (i = 28; i <= 63; i++) {
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_4[ac_y_table], i,
- s->first_coded_y_fragment, s->last_coded_y_fragment, residual_eob_run);
+ 1, residual_eob_run);
residual_eob_run = unpack_vlcs(s, gb, &s->ac_vlc_4[ac_c_table], i,
- s->first_coded_c_fragment, s->last_coded_c_fragment, residual_eob_run);
+ 0, residual_eob_run);
}
return 0;
@@ -1756,9 +1803,10 @@ static av_cold int vp3_decode_init(AVCodecContext *avctx)
s->coeff_counts = av_malloc(s->fragment_count * sizeof(*s->coeff_counts));
s->coeffs = av_malloc(s->fragment_count * sizeof(Coeff) * 65);
s->coded_fragment_list = av_malloc(s->fragment_count * sizeof(int));
+ s->fast_fragment_list = av_malloc(s->fragment_count * sizeof(int));
s->pixel_addresses_initialized = 0;
if (!s->superblock_coding || !s->all_fragments || !s->coeff_counts ||
- !s->coeffs || !s->coded_fragment_list) {
+ !s->coeffs || !s->coded_fragment_list || !s->fast_fragment_list) {
vp3_decode_end(avctx);
return -1;
}
@@ -2057,6 +2105,7 @@ static av_cold int vp3_decode_end(AVCodecContext *avctx)
av_free(s->coeff_counts);
av_free(s->coeffs);
av_free(s->coded_fragment_list);
+ av_free(s->fast_fragment_list);
av_free(s->superblock_fragments);
av_free(s->superblock_macroblocks);
av_free(s->macroblock_fragments);