theora decoding support (only keyframes for now, because by theora the frame isn...
authorAlex Beregszaszi <alex@rtfs.hu>
Sat, 11 Oct 2003 17:44:21 +0000 (17:44 +0000)
committerAlex Beregszaszi <alex@rtfs.hu>
Sat, 11 Oct 2003 17:44:21 +0000 (17:44 +0000)
Originally committed as revision 2359 to svn://svn.ffmpeg.org/ffmpeg/trunk

libavcodec/allcodecs.c
libavcodec/avcodec.h
libavcodec/vp3.c

index ca6f500..7762c3f 100644 (file)
@@ -117,6 +117,7 @@ void avcodec_register_all(void)
     register_avcodec(&cyuv_decoder);
     register_avcodec(&h264_decoder);
     register_avcodec(&vp3_decoder);
+    register_avcodec(&theora_decoder);
     register_avcodec(&asv1_decoder);
     register_avcodec(&asv2_decoder);
     register_avcodec(&vcr1_decoder);
index b0b3bf5..1f57584 100644 (file)
@@ -61,6 +61,7 @@ enum CodecID {
     CODEC_ID_H264,
     CODEC_ID_INDEO3,
     CODEC_ID_VP3,
+    CODEC_ID_THEORA,
     CODEC_ID_AAC,
     CODEC_ID_MPEG4AAC,
     CODEC_ID_ASV1,
@@ -1433,6 +1434,7 @@ extern AVCodec cyuv_decoder;
 extern AVCodec h264_decoder;
 extern AVCodec indeo3_decoder;
 extern AVCodec vp3_decoder;
+extern AVCodec theora_decoder;
 extern AVCodec amr_nb_decoder;
 extern AVCodec amr_nb_encoder;
 extern AVCodec amr_wb_encoder;
index 0000778..315e185 100644 (file)
@@ -20,6 +20,8 @@
  * For more information about the VP3 coding process, visit:
  *   http://www.pcisys.net/~melanson/codecs/
  *
+ * Theora decoder by Alex Beregszaszi
+ *
  */
 
 /**
@@ -213,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;
@@ -245,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 */
@@ -1130,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");
@@ -1151,17 +1161,17 @@ static void init_dequantizer(Vp3DecodeContext *s)
 #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;
@@ -1172,17 +1182,17 @@ 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;
@@ -2614,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++) {
 
@@ -2677,24 +2701,35 @@ 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);
+    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);
@@ -2720,9 +2755,6 @@ static int vp3_decode_frame(AVCodecContext *avctx,
             vp3_calculate_pixel_addresses(s);
 
     } else {
-
-        debug_vp3("\n");
-
         /* allocate a new current frame */
         s->current_frame.reference = 3;
         if(avctx->get_buffer(avctx, &s->current_frame) < 0) {
@@ -2818,6 +2850,114 @@ 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_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:
+           /* comment */
+           break;
+       case 0x82:
+           theora_decode_tables(avctx, gb);
+           break;
+    }
+
+    return 0;
+}
+
 AVCodec vp3_decoder = {
     "vp3",
     CODEC_TYPE_VIDEO,
@@ -2830,3 +2970,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
+};