summaryrefslogtreecommitdiff
path: root/src/libffmpeg/libavcodec/vp3.c
diff options
context:
space:
mode:
authorMike Melanson <mike@multimedia.cx>2003-10-27 15:24:38 +0000
committerMike Melanson <mike@multimedia.cx>2003-10-27 15:24:38 +0000
commitc5b6afab8b74e5cc938b8467d3808a877ded7d03 (patch)
tree4a9738571b6330c8895c6ad3faec4d68f72fbb16 /src/libffmpeg/libavcodec/vp3.c
parentd2a72f348508fd0a78a80f4da795dcf3155f02bc (diff)
downloadxine-lib-c5b6afab8b74e5cc938b8467d3808a877ded7d03.tar.gz
xine-lib-c5b6afab8b74e5cc938b8467d3808a877ded7d03.tar.bz2
super mega ffmpeg tree sync
CVS patchset: 5615 CVS date: 2003/10/27 15:24:38
Diffstat (limited to 'src/libffmpeg/libavcodec/vp3.c')
-rw-r--r--src/libffmpeg/libavcodec/vp3.c627
1 files changed, 539 insertions, 88 deletions
diff --git a/src/libffmpeg/libavcodec/vp3.c b/src/libffmpeg/libavcodec/vp3.c
index 1f87086c2..c72c7fc16 100644
--- a/src/libffmpeg/libavcodec/vp3.c
+++ b/src/libffmpeg/libavcodec/vp3.c
@@ -17,6 +17,10 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* VP3 Video Decoder by Mike Melanson (melanson@pcisys.net)
+ * For more information about the VP3 coding process, visit:
+ * http://www.pcisys.net/~melanson/codecs/
+ *
+ * Theora decoder by Alex Beregszaszi
*
*/
@@ -211,6 +215,7 @@ static int ModeAlphabet[7][CODING_MODE_COUNT] =
typedef struct Vp3DecodeContext {
AVCodecContext *avctx;
+ int theora, theora_tables;
int width, height;
AVFrame golden_frame;
AVFrame last_frame;
@@ -243,6 +248,13 @@ typedef struct Vp3DecodeContext {
Vp3Fragment *all_fragments;
int u_fragment_start;
int v_fragment_start;
+
+ /* tables */
+ uint16_t coded_dc_scale_factor[64];
+ uint32_t coded_quality_threshold[64];
+ uint16_t coded_intra_y_dequant[64];
+ uint16_t coded_intra_c_dequant[64];
+ uint16_t coded_inter_dequant[64];
/* this is a list of indices into the all_fragments array indicating
* which of the fragments are coded */
@@ -285,9 +297,312 @@ typedef struct Vp3DecodeContext {
int last_coded_y_fragment;
int last_coded_c_fragment;
+ uint8_t edge_emu_buffer[9*2048]; //FIXME dynamic alloc
+ uint8_t qscale_table[2048]; //FIXME dynamic alloc (width+15)/16
} Vp3DecodeContext;
/************************************************************************
+ * VP3 I/DCT
+ ************************************************************************/
+
+#define IdctAdjustBeforeShift 8
+#define xC1S7 64277
+#define xC2S6 60547
+#define xC3S5 54491
+#define xC4S4 46341
+#define xC5S3 36410
+#define xC6S2 25080
+#define xC7S1 12785
+
+void vp3_idct_c(int16_t *input_data, int16_t *dequant_matrix,
+ int16_t *output_data)
+{
+ int32_t intermediate_data[64];
+ int32_t *ip = intermediate_data;
+ int16_t *op = output_data;
+
+ int32_t A_, B_, C_, D_, _Ad, _Bd, _Cd, _Dd, E_, F_, G_, H_;
+ int32_t _Ed, _Gd, _Add, _Bdd, _Fd, _Hd;
+ int32_t t1, t2;
+
+ int i, j;
+
+ debug_idct("raw coefficient block:\n");
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ debug_idct(" %5d", input_data[i * 8 + j]);
+ }
+ debug_idct("\n");
+ }
+ debug_idct("\n");
+
+ for (i = 0; i < 64; i++) {
+ j = dezigzag_index[i];
+ intermediate_data[j] = dequant_matrix[i] * input_data[i];
+ }
+
+ debug_idct("dequantized block:\n");
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ debug_idct(" %5d", intermediate_data[i * 8 + j]);
+ }
+ debug_idct("\n");
+ }
+ debug_idct("\n");
+
+ /* Inverse DCT on the rows now */
+ for (i = 0; i < 8; i++) {
+ /* Check for non-zero values */
+ if ( ip[0] | ip[1] | ip[2] | ip[3] | ip[4] | ip[5] | ip[6] | ip[7] ) {
+ t1 = (int32_t)(xC1S7 * ip[1]);
+ t2 = (int32_t)(xC7S1 * ip[7]);
+ t1 >>= 16;
+ t2 >>= 16;
+ A_ = t1 + t2;
+
+ t1 = (int32_t)(xC7S1 * ip[1]);
+ t2 = (int32_t)(xC1S7 * ip[7]);
+ t1 >>= 16;
+ t2 >>= 16;
+ B_ = t1 - t2;
+
+ t1 = (int32_t)(xC3S5 * ip[3]);
+ t2 = (int32_t)(xC5S3 * ip[5]);
+ t1 >>= 16;
+ t2 >>= 16;
+ C_ = t1 + t2;
+
+ t1 = (int32_t)(xC3S5 * ip[5]);
+ t2 = (int32_t)(xC5S3 * ip[3]);
+ t1 >>= 16;
+ t2 >>= 16;
+ D_ = t1 - t2;
+
+
+ t1 = (int32_t)(xC4S4 * (A_ - C_));
+ t1 >>= 16;
+ _Ad = t1;
+
+ t1 = (int32_t)(xC4S4 * (B_ - D_));
+ t1 >>= 16;
+ _Bd = t1;
+
+
+ _Cd = A_ + C_;
+ _Dd = B_ + D_;
+
+ t1 = (int32_t)(xC4S4 * (ip[0] + ip[4]));
+ t1 >>= 16;
+ E_ = t1;
+
+ t1 = (int32_t)(xC4S4 * (ip[0] - ip[4]));
+ t1 >>= 16;
+ F_ = t1;
+
+ t1 = (int32_t)(xC2S6 * ip[2]);
+ t2 = (int32_t)(xC6S2 * ip[6]);
+ t1 >>= 16;
+ t2 >>= 16;
+ G_ = t1 + t2;
+
+ t1 = (int32_t)(xC6S2 * ip[2]);
+ t2 = (int32_t)(xC2S6 * ip[6]);
+ t1 >>= 16;
+ t2 >>= 16;
+ H_ = t1 - t2;
+
+
+ _Ed = E_ - G_;
+ _Gd = E_ + G_;
+
+ _Add = F_ + _Ad;
+ _Bdd = _Bd - H_;
+
+ _Fd = F_ - _Ad;
+ _Hd = _Bd + H_;
+
+ /* Final sequence of operations over-write original inputs. */
+ ip[0] = (int16_t)((_Gd + _Cd ) >> 0);
+ ip[7] = (int16_t)((_Gd - _Cd ) >> 0);
+
+ ip[1] = (int16_t)((_Add + _Hd ) >> 0);
+ ip[2] = (int16_t)((_Add - _Hd ) >> 0);
+
+ ip[3] = (int16_t)((_Ed + _Dd ) >> 0);
+ ip[4] = (int16_t)((_Ed - _Dd ) >> 0);
+
+ ip[5] = (int16_t)((_Fd + _Bdd ) >> 0);
+ ip[6] = (int16_t)((_Fd - _Bdd ) >> 0);
+
+ }
+
+ ip += 8; /* next row */
+ }
+
+ ip = intermediate_data;
+
+ for ( i = 0; i < 8; i++) {
+ /* Check for non-zero values (bitwise or faster than ||) */
+ if ( ip[0 * 8] | ip[1 * 8] | ip[2 * 8] | ip[3 * 8] |
+ ip[4 * 8] | ip[5 * 8] | ip[6 * 8] | ip[7 * 8] ) {
+
+ t1 = (int32_t)(xC1S7 * ip[1*8]);
+ t2 = (int32_t)(xC7S1 * ip[7*8]);
+ t1 >>= 16;
+ t2 >>= 16;
+ A_ = t1 + t2;
+
+ t1 = (int32_t)(xC7S1 * ip[1*8]);
+ t2 = (int32_t)(xC1S7 * ip[7*8]);
+ t1 >>= 16;
+ t2 >>= 16;
+ B_ = t1 - t2;
+
+ t1 = (int32_t)(xC3S5 * ip[3*8]);
+ t2 = (int32_t)(xC5S3 * ip[5*8]);
+ t1 >>= 16;
+ t2 >>= 16;
+ C_ = t1 + t2;
+
+ t1 = (int32_t)(xC3S5 * ip[5*8]);
+ t2 = (int32_t)(xC5S3 * ip[3*8]);
+ t1 >>= 16;
+ t2 >>= 16;
+ D_ = t1 - t2;
+
+
+ t1 = (int32_t)(xC4S4 * (A_ - C_));
+ t1 >>= 16;
+ _Ad = t1;
+
+ t1 = (int32_t)(xC4S4 * (B_ - D_));
+ t1 >>= 16;
+ _Bd = t1;
+
+
+ _Cd = A_ + C_;
+ _Dd = B_ + D_;
+
+ t1 = (int32_t)(xC4S4 * (ip[0*8] + ip[4*8]));
+ t1 >>= 16;
+ E_ = t1;
+
+ t1 = (int32_t)(xC4S4 * (ip[0*8] - ip[4*8]));
+ t1 >>= 16;
+ F_ = t1;
+
+ t1 = (int32_t)(xC2S6 * ip[2*8]);
+ t2 = (int32_t)(xC6S2 * ip[6*8]);
+ t1 >>= 16;
+ t2 >>= 16;
+ G_ = t1 + t2;
+
+ t1 = (int32_t)(xC6S2 * ip[2*8]);
+ t2 = (int32_t)(xC2S6 * ip[6*8]);
+ t1 >>= 16;
+ t2 >>= 16;
+ H_ = t1 - t2;
+
+
+ _Ed = E_ - G_;
+ _Gd = E_ + G_;
+
+ _Add = F_ + _Ad;
+ _Bdd = _Bd - H_;
+
+ _Fd = F_ - _Ad;
+ _Hd = _Bd + H_;
+
+ _Gd += IdctAdjustBeforeShift;
+ _Add += IdctAdjustBeforeShift;
+ _Ed += IdctAdjustBeforeShift;
+ _Fd += IdctAdjustBeforeShift;
+
+ /* Final sequence of operations over-write original inputs. */
+ op[0*8] = (int16_t)((_Gd + _Cd ) >> 4);
+ op[7*8] = (int16_t)((_Gd - _Cd ) >> 4);
+
+ op[1*8] = (int16_t)((_Add + _Hd ) >> 4);
+ op[2*8] = (int16_t)((_Add - _Hd ) >> 4);
+
+ op[3*8] = (int16_t)((_Ed + _Dd ) >> 4);
+ op[4*8] = (int16_t)((_Ed - _Dd ) >> 4);
+
+ op[5*8] = (int16_t)((_Fd + _Bdd ) >> 4);
+ op[6*8] = (int16_t)((_Fd - _Bdd ) >> 4);
+
+ } else {
+
+ op[0*8] = 0;
+ op[7*8] = 0;
+ op[1*8] = 0;
+ op[2*8] = 0;
+ op[3*8] = 0;
+ op[4*8] = 0;
+ op[5*8] = 0;
+ op[6*8] = 0;
+ }
+
+ ip++; /* next column */
+ op++;
+ }
+}
+
+void vp3_idct_put(int16_t *input_data, int16_t *dequant_matrix,
+ uint8_t *dest, int stride)
+{
+ int16_t transformed_data[64];
+ int16_t *op;
+ int i, j;
+
+ vp3_idct_c(input_data, dequant_matrix, transformed_data);
+
+ /* place in final output */
+ op = transformed_data;
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ if (*op < -128)
+ *dest = 0;
+ else if (*op > 127)
+ *dest = 255;
+ else
+ *dest = (uint8_t)(*op + 128);
+ op++;
+ dest++;
+ }
+ dest += (stride - 8);
+ }
+}
+
+void vp3_idct_add(int16_t *input_data, int16_t *dequant_matrix,
+ uint8_t *dest, int stride)
+{
+ int16_t transformed_data[64];
+ int16_t *op;
+ int i, j;
+ int16_t sample;
+
+ vp3_idct_c(input_data, dequant_matrix, transformed_data);
+
+ /* place in final output */
+ op = transformed_data;
+ for (i = 0; i < 8; i++) {
+ for (j = 0; j < 8; j++) {
+ sample = *dest + *op;
+ if (sample < 0)
+ *dest = 0;
+ else if (sample > 255)
+ *dest = 255;
+ else
+ *dest = (uint8_t)(sample & 0xFF);
+ op++;
+ dest++;
+ }
+ dest += (stride - 8);
+ }
+}
+
+/************************************************************************
* VP3 specific functions
************************************************************************/
@@ -825,8 +1140,8 @@ s->all_fragments[i].motion_y = 0xbeef;
static void init_dequantizer(Vp3DecodeContext *s)
{
- int quality_scale = vp31_quality_threshold[s->quality_index];
- int dc_scale_factor = vp31_dc_scale_factor[s->quality_index];
+ int quality_scale = s->coded_quality_threshold[s->quality_index];
+ int dc_scale_factor = s->coded_dc_scale_factor[s->quality_index];
int i, j;
debug_vp3(" vp3: initializing dequantization tables\n");
@@ -843,20 +1158,20 @@ static void init_dequantizer(Vp3DecodeContext *s)
*
* Then, saturate the result to a lower limit of MIN_DEQUANT_VAL.
*/
-#define SCALER 1
+#define SCALER 4
/* scale DC quantizers */
- s->intra_y_dequant[0] = vp31_intra_y_dequant[0] * dc_scale_factor / 100;
+ s->intra_y_dequant[0] = s->coded_intra_y_dequant[0] * dc_scale_factor / 100;
if (s->intra_y_dequant[0] < MIN_DEQUANT_VAL * 2)
s->intra_y_dequant[0] = MIN_DEQUANT_VAL * 2;
s->intra_y_dequant[0] *= SCALER;
- s->intra_c_dequant[0] = vp31_intra_c_dequant[0] * dc_scale_factor / 100;
+ s->intra_c_dequant[0] = s->coded_intra_c_dequant[0] * dc_scale_factor / 100;
if (s->intra_c_dequant[0] < MIN_DEQUANT_VAL * 2)
s->intra_c_dequant[0] = MIN_DEQUANT_VAL * 2;
s->intra_c_dequant[0] *= SCALER;
- s->inter_dequant[0] = vp31_inter_dequant[0] * dc_scale_factor / 100;
+ s->inter_dequant[0] = s->coded_inter_dequant[0] * dc_scale_factor / 100;
if (s->inter_dequant[0] < MIN_DEQUANT_VAL * 4)
s->inter_dequant[0] = MIN_DEQUANT_VAL * 4;
s->inter_dequant[0] *= SCALER;
@@ -867,21 +1182,23 @@ static void init_dequantizer(Vp3DecodeContext *s)
j = zigzag_index[i];
- s->intra_y_dequant[j] = vp31_intra_y_dequant[i] * quality_scale / 100;
+ s->intra_y_dequant[j] = s->coded_intra_y_dequant[i] * quality_scale / 100;
if (s->intra_y_dequant[j] < MIN_DEQUANT_VAL)
s->intra_y_dequant[j] = MIN_DEQUANT_VAL;
s->intra_y_dequant[j] *= SCALER;
- s->intra_c_dequant[j] = vp31_intra_c_dequant[i] * quality_scale / 100;
+ s->intra_c_dequant[j] = s->coded_intra_c_dequant[i] * quality_scale / 100;
if (s->intra_c_dequant[j] < MIN_DEQUANT_VAL)
s->intra_c_dequant[j] = MIN_DEQUANT_VAL;
s->intra_c_dequant[j] *= SCALER;
- s->inter_dequant[j] = vp31_inter_dequant[i] * quality_scale / 100;
+ s->inter_dequant[j] = s->coded_inter_dequant[i] * quality_scale / 100;
if (s->inter_dequant[j] < MIN_DEQUANT_VAL * 2)
s->inter_dequant[j] = MIN_DEQUANT_VAL * 2;
s->inter_dequant[j] *= SCALER;
}
+
+ memset(s->qscale_table, (FFMAX(s->intra_y_dequant[1], s->intra_c_dequant[1])+8)/16, 512); //FIXME finetune
/* print debug information as requested */
debug_dequantizers("intra Y dequantizers:\n");
@@ -2029,10 +2346,7 @@ static void render_fragments(Vp3DecodeContext *s,
int x, y;
int m, n;
int i = first_fragment;
- int j;
int16_t *dequantizer;
- DCTELEM dequant_block[64];
- DCTELEM dequant_block_permuted[64];
unsigned char *output_plane;
unsigned char *last_plane;
unsigned char *golden_plane;
@@ -2040,7 +2354,7 @@ static void render_fragments(Vp3DecodeContext *s,
int motion_x, motion_y;
int upper_motion_limit, lower_motion_limit;
int motion_halfpel_index;
- unsigned int motion_source;
+ uint8_t *motion_source;
debug_vp3(" vp3: rendering final fragments for %s\n",
(plane == 0) ? "Y plane" : (plane == 1) ? "U plane" : "V plane");
@@ -2086,63 +2400,55 @@ static void render_fragments(Vp3DecodeContext *s,
/* transform if this block was coded */
if (s->all_fragments[i].coding_method != MODE_COPY) {
- motion_source = s->all_fragments[i].first_pixel;
+ if ((s->all_fragments[i].coding_method == MODE_USING_GOLDEN) ||
+ (s->all_fragments[i].coding_method == MODE_GOLDEN_MV))
+ motion_source= golden_plane;
+ else
+ motion_source= last_plane;
+
+ motion_source += s->all_fragments[i].first_pixel;
motion_halfpel_index = 0;
/* sort out the motion vector if this fragment is coded
* using a motion vector method */
if ((s->all_fragments[i].coding_method > MODE_INTRA) &&
(s->all_fragments[i].coding_method != MODE_USING_GOLDEN)) {
+ int src_x, src_y;
motion_x = s->all_fragments[i].motion_x;
motion_y = s->all_fragments[i].motion_y;
+ if(plane){
+ motion_x= (motion_x>>1) | (motion_x&1);
+ motion_y= (motion_y>>1) | (motion_y&1);
+ }
+
+ src_x= (motion_x>>1) + x;
+ src_y= (motion_y>>1) + y;
if ((motion_x == 0xbeef) || (motion_y == 0xbeef))
printf (" help! got beefy vector! (%X, %X)\n", motion_x, motion_y);
- if (motion_x >= 0) {
- motion_halfpel_index = motion_x & 0x01;
- motion_source += (motion_x >> 1);
- } else {
- motion_x = -motion_x;
- motion_halfpel_index = motion_x & 0x01;
- motion_source -= ((motion_x + 1) >> 1);
- }
+ motion_halfpel_index = motion_x & 0x01;
+ motion_source += (motion_x >> 1);
// motion_y = -motion_y;
- if (motion_y >= 0) {
- motion_halfpel_index |= (motion_y & 0x01) << 1;
- motion_source += ((motion_y >> 1) * stride);
- } else {
- motion_y = -motion_y;
- motion_halfpel_index |= (motion_y & 0x01) << 1;
- motion_source -= (((motion_y + 1) >> 1) * stride);
- }
+ motion_halfpel_index |= (motion_y & 0x01) << 1;
+ motion_source += ((motion_y >> 1) * stride);
- /* if the are any problems with a motion vector, refuse
- * to render the block */
- if ((motion_source < upper_motion_limit) ||
- (motion_source > lower_motion_limit)) {
- printf (" vp3: help! motion source (%d) out of range (%d..%d), fragment %d\n",
- motion_source, upper_motion_limit, lower_motion_limit, i);
- continue;
+ if(src_x<0 || src_y<0 || src_x + 9 >= width || src_y + 9 >= height){
+ uint8_t *temp= s->edge_emu_buffer;
+ if(stride<0) temp -= 9*stride;
+
+ ff_emulated_edge_mc(temp, motion_source, stride, 9, 9, src_x, src_y, width, height);
+ motion_source= temp;
}
}
/* first, take care of copying a block from either the
* previous or the golden frame */
- if ((s->all_fragments[i].coding_method == MODE_USING_GOLDEN) ||
- (s->all_fragments[i].coding_method == MODE_GOLDEN_MV)) {
-
- s->dsp.put_pixels_tab[1][motion_halfpel_index](
- output_plane + s->all_fragments[i].first_pixel,
- golden_plane + motion_source,
- stride, 8);
-
- } else
if (s->all_fragments[i].coding_method != MODE_INTRA) {
- s->dsp.put_pixels_tab[1][motion_halfpel_index](
+ s->dsp.put_no_rnd_pixels_tab[1][motion_halfpel_index](
output_plane + s->all_fragments[i].first_pixel,
- last_plane + motion_source,
+ motion_source,
stride, 8);
}
@@ -2150,34 +2456,16 @@ printf (" help! got beefy vector! (%X, %X)\n", motion_x, motion_y);
debug_idct("fragment %d, coding mode %d, DC = %d, dequant = %d:\n",
i, s->all_fragments[i].coding_method,
s->all_fragments[i].coeffs[0], dequantizer[0]);
- for (j = 0; j < 64; j++)
- dequant_block[dezigzag_index[j]] =
- s->all_fragments[i].coeffs[j] *
- dequantizer[j];
- for (j = 0; j < 64; j++)
- dequant_block_permuted[s->dsp.idct_permutation[j]] =
- dequant_block[j];
-
- debug_idct("dequantized block:\n");
- for (m = 0; m < 8; m++) {
- for (n = 0; n < 8; n++) {
- debug_idct(" %5d", dequant_block[m * 8 + n]);
- }
- debug_idct("\n");
- }
- debug_idct("\n");
/* invert DCT and place (or add) in final output */
-
if (s->all_fragments[i].coding_method == MODE_INTRA) {
- dequant_block_permuted[0] += 1024;
- s->dsp.idct_put(
+ vp3_idct_put(s->all_fragments[i].coeffs, dequantizer,
output_plane + s->all_fragments[i].first_pixel,
- stride, dequant_block_permuted);
+ stride);
} else {
- s->dsp.idct_add(
+ vp3_idct_add(s->all_fragments[i].coeffs, dequantizer,
output_plane + s->all_fragments[i].first_pixel,
- stride, dequant_block_permuted);
+ stride);
}
debug_idct("block after idct_%s():\n",
@@ -2336,6 +2624,20 @@ static int vp3_decode_init(AVCodecContext *avctx)
s->coded_fragment_list = av_malloc(s->fragment_count * sizeof(int));
s->pixel_addresses_inited = 0;
+ if (!s->theora_tables)
+ {
+ for (i = 0; i < 64; i++)
+ s->coded_dc_scale_factor[i] = vp31_dc_scale_factor[i];
+ for (i = 0; i < 64; i++)
+ s->coded_quality_threshold[i] = vp31_quality_threshold[i];
+ for (i = 0; i < 64; i++)
+ s->coded_intra_y_dequant[i] = vp31_intra_y_dequant[i];
+ for (i = 0; i < 64; i++)
+ s->coded_intra_c_dequant[i] = vp31_intra_c_dequant[i];
+ for (i = 0; i < 64; i++)
+ s->coded_inter_dequant[i] = vp31_inter_dequant[i];
+ }
+
/* init VLC tables */
for (i = 0; i < 16; i++) {
@@ -2382,8 +2684,6 @@ static int vp3_decode_init(AVCodecContext *avctx)
s->golden_frame.data[i] = NULL;
}
-avctx->flags |= CODEC_FLAG_GRAY;
-
return 0;
}
@@ -2401,29 +2701,39 @@ static int vp3_decode_frame(AVCodecContext *avctx,
*data_size = 0;
init_get_bits(&gb, buf, buf_size * 8);
+
+ if (s->theora && get_bits1(&gb))
+ {
+ printf("Theora: bad frame indicator\n");
+ return -1;
+ }
- s->keyframe = get_bits(&gb, 1);
- s->keyframe ^= 1;
- skip_bits(&gb, 1);
+ s->keyframe = !get_bits1(&gb);
+ if (s->theora && s->keyframe)
+ {
+ if (get_bits1(&gb))
+ printf("Theora: warning, unsupported keyframe coding type?!\n");
+ skip_bits(&gb, 2); /* reserved? */
+ }
+ else
+ skip_bits(&gb, 1);
s->last_quality_index = s->quality_index;
s->quality_index = get_bits(&gb, 6);
- debug_vp3(" VP3 frame #%d: Q index = %d", counter, s->quality_index);
-printf (" frame #%d\n", counter);
+ debug_vp3(" VP3 %sframe #%d: Q index = %d\n",
+ s->keyframe?"key":"", counter, s->quality_index);
counter++;
if (s->quality_index != s->last_quality_index)
init_dequantizer(s);
if (s->keyframe) {
-
- debug_vp3(", keyframe\n");
/* skip the other 2 header bytes for now */
- skip_bits(&gb, 16);
-
+ if (!s->theora) skip_bits(&gb, 16);
if (s->last_frame.data[0] == s->golden_frame.data[0]) {
if (s->golden_frame.data[0])
avctx->release_buffer(avctx, &s->golden_frame);
+ s->last_frame= s->golden_frame; /* ensure that we catch any access to this released frame */
} else {
if (s->golden_frame.data[0])
avctx->release_buffer(avctx, &s->golden_frame);
@@ -2431,7 +2741,7 @@ printf (" frame #%d\n", counter);
avctx->release_buffer(avctx, &s->last_frame);
}
- s->golden_frame.reference = 0;
+ s->golden_frame.reference = 3;
if(avctx->get_buffer(avctx, &s->golden_frame) < 0) {
printf("vp3: get_buffer() failed\n");
return -1;
@@ -2445,17 +2755,17 @@ printf (" frame #%d\n", counter);
vp3_calculate_pixel_addresses(s);
} else {
-
- debug_vp3("\n");
-
/* allocate a new current frame */
- s->current_frame.reference = 0;
+ s->current_frame.reference = 3;
if(avctx->get_buffer(avctx, &s->current_frame) < 0) {
printf("vp3: get_buffer() failed\n");
return -1;
}
}
+ s->current_frame.qscale_table= s->qscale_table; //FIXME allocate individual tables per AVFrame
+ s->current_frame.qstride= 0;
+
init_frame(s, &gb);
#if KEYFRAMES_ONLY
@@ -2510,6 +2820,7 @@ if (!s->keyframe) {
/* shuffle frames (last = current) */
memcpy(&s->last_frame, &s->current_frame, sizeof(AVFrame));
+ s->current_frame.data[0]= NULL; /* ensure that we catch any access to this released frame */
return buf_size;
}
@@ -2527,9 +2838,9 @@ static int vp3_decode_end(AVCodecContext *avctx)
av_free(s->superblock_macroblocks);
av_free(s->macroblock_fragments);
av_free(s->macroblock_coding);
-
+
/* release all frames */
- if (s->golden_frame.data[0])
+ if (s->golden_frame.data[0] && s->golden_frame.data[0] != s->last_frame.data[0])
avctx->release_buffer(avctx, &s->golden_frame);
if (s->last_frame.data[0])
avctx->release_buffer(avctx, &s->last_frame);
@@ -2539,6 +2850,133 @@ static int vp3_decode_end(AVCodecContext *avctx)
return 0;
}
+/* current version is 3.2.0 */
+
+static int theora_decode_header(AVCodecContext *avctx, GetBitContext gb)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+
+ skip_bits(&gb, 8); /* version major */
+ skip_bits(&gb, 8); /* version minor */
+ skip_bits(&gb, 8); /* version micro */
+
+ s->width = get_bits(&gb, 16) << 4;
+ s->height = get_bits(&gb, 16) << 4;
+
+ skip_bits(&gb, 24); /* frame width */
+ skip_bits(&gb, 24); /* frame height */
+
+ skip_bits(&gb, 8); /* offset x */
+ skip_bits(&gb, 8); /* offset y */
+
+ skip_bits(&gb, 32); /* fps numerator */
+ skip_bits(&gb, 32); /* fps denumerator */
+ skip_bits(&gb, 24); /* aspect numerator */
+ skip_bits(&gb, 24); /* aspect denumerator */
+
+ skip_bits(&gb, 5); /* keyframe frequency force */
+ skip_bits(&gb, 8); /* colorspace */
+ skip_bits(&gb, 24); /* bitrate */
+
+ skip_bits(&gb, 6); /* last(?) quality index */
+
+// align_get_bits(&gb);
+
+ avctx->width = s->width;
+ avctx->height = s->height;
+
+ vp3_decode_init(avctx);
+
+ return 0;
+}
+
+static int theora_decode_comments(AVCodecContext *avctx, GetBitContext gb)
+{
+ int nb_comments, i, tmp;
+
+ tmp = get_bits(&gb, 32);
+ while(tmp-=8)
+ skip_bits(&gb, 8);
+
+ nb_comments = get_bits(&gb, 32);
+ for (i = 0; i < nb_comments; i++)
+ {
+ tmp = get_bits(&gb, 32);
+ while(tmp-=8)
+ skip_bits(&gb, 8);
+ }
+
+ return 0;
+}
+
+static int theora_decode_tables(AVCodecContext *avctx, GetBitContext gb)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+ int i;
+
+ /* quality threshold table */
+ for (i = 0; i < 64; i++)
+ s->coded_quality_threshold[i] = get_bits(&gb, 16);
+
+ /* dc scale factor table */
+ for (i = 0; i < 64; i++)
+ s->coded_dc_scale_factor[i] = get_bits(&gb, 16);
+
+ /* y coeffs */
+ for (i = 0; i < 64; i++)
+ s->coded_intra_y_dequant[i] = get_bits(&gb, 8);
+
+ /* uv coeffs */
+ for (i = 0; i < 64; i++)
+ s->coded_intra_c_dequant[i] = get_bits(&gb, 8);
+
+ /* inter coeffs */
+ for (i = 0; i < 64; i++)
+ s->coded_inter_dequant[i] = get_bits(&gb, 8);
+
+ s->theora_tables = 1;
+
+ return 0;
+}
+
+static int theora_decode_init(AVCodecContext *avctx)
+{
+ Vp3DecodeContext *s = avctx->priv_data;
+ GetBitContext gb;
+ int ptype;
+
+ s->theora = 1;
+
+ if (!avctx->extradata_size)
+ return -1;
+
+ init_get_bits(&gb, avctx->extradata, avctx->extradata_size);
+
+ ptype = get_bits(&gb, 8);
+ debug_vp3("Theora headerpacket type: %x\n", ptype);
+
+ if (!(ptype & 0x80))
+ return -1;
+
+ skip_bits(&gb, 6*8); /* "theora" */
+
+ switch(ptype)
+ {
+ case 0x80:
+ theora_decode_header(avctx, gb);
+ vp3_decode_init(avctx);
+ break;
+ case 0x81:
+ theora_decode_comments(avctx, gb);
+ break;
+ case 0x82:
+ theora_decode_tables(avctx, gb);
+ break;
+ }
+
+ return 0;
+}
+
AVCodec vp3_decoder = {
"vp3",
CODEC_TYPE_VIDEO,
@@ -2551,3 +2989,16 @@ AVCodec vp3_decoder = {
0,
NULL
};
+
+AVCodec theora_decoder = {
+ "theora",
+ CODEC_TYPE_VIDEO,
+ CODEC_ID_THEORA,
+ sizeof(Vp3DecodeContext),
+ theora_decode_init,
+ NULL,
+ vp3_decode_end,
+ vp3_decode_frame,
+ 0,
+ NULL
+};