[FFmpeg-devel] [PATCH] Support block-level quantization in Theora

David Conrad lessen42
Fri May 29 23:43:30 CEST 2009


On May 29, 2009, at 3:52 PM, Michael Niedermayer wrote:

> On Thu, May 28, 2009 at 06:56:06PM -0400, David Conrad wrote:
>> On May 28, 2009, at 5:46 PM, Michael Niedermayer wrote:
>>
>>> On Thu, May 28, 2009 at 01:32:02PM -0400, David Conrad wrote:
>>>> Hi,
>>>>
>>>> This mostly fixes theora_derf.ogg [1]; keyframes are good but  
>>>> interframes
>>>> degrade due to a bug in libtheora when that file was created  
>>>> (inter quant
>>>> matrices were assumed to be copied from intra when they shouldn't  
>>>> have
>>>> been
>>>> according to the spec.)
>>>>
>>>> Also I reduced the number of planes in qmat to 3 because Theora/ 
>>>> vp3 can't
>>>> have more.
>>>>
>>>> [1]
>>>> http://ftp.icm.edu.pl/pub/unix/video/mplayer/samples/ogg/Theora/theora_derf.ogg
>>>>
>>>
>>>> commit c1a1975b43c1c4f1a2ec62a556348455828a22dd
>>>> Author: David Conrad <lessen42 at gmail.com>
>>>> Date:   Thu May 28 13:30:57 2009 -0400
>>>>
>>>>   Support block-level quantization in Theora
>>>>
>>>> diff --git a/libavcodec/vp3.c b/libavcodec/vp3.c
>>>> index 9f7dfb6..5d4be28 100644
>>>> --- a/libavcodec/vp3.c
>>>> +++ b/libavcodec/vp3.c
>>>> @@ -60,6 +60,7 @@ typedef struct Vp3Fragment {
>>>>    uint8_t coding_method;
>>>>    int8_t motion_x;
>>>>    int8_t motion_y;
>>>> +    uint8_t qi;
>>>> } Vp3Fragment;
>>>
>>> what is qi ?
>>> is it what everyone but xiph calls qp? if so i would prefer to  
>>> follow
>>> what the majority calls it.
>>
>> Xiph does indeed call qp qi. However, here it's an index into the 3  
>> qps
>> that are defined for the frame (I was thinking quant index.) So  
>> maybe this
>> should be called qpi?
>>
>>> [...]
>>>> @@ -477,10 +478,10 @@ static void init_frame(Vp3DecodeContext *s,
>>>> GetBitContext *gb)
>>>> * This function sets up the dequantization tables used for a  
>>>> particular
>>>> * frame.
>>>> */
>>>> -static void init_dequantizer(Vp3DecodeContext *s)
>>>> +static void init_dequantizer(Vp3DecodeContext *s, int qi)
>>>> {
>>>> -    int ac_scale_factor = s->coded_ac_scale_factor[s- 
>>>> >quality_index];
>>>> -    int dc_scale_factor = s->coded_dc_scale_factor[s- 
>>>> >quality_index];
>>>
>>>> +    int ac_scale_factor = s->coded_ac_scale_factor[s->qis[qi]];
>>>> +    int dc_scale_factor = s->coded_dc_scale_factor[s->qis[qi]];
>>>
>>> qis is hardly a better name than qi btw ...
>>> "quality_index" at least made some sense
>>
>> In this case it already existed :) I renamed it qps, though maybe  
>> it should
>> be frame_qps?
>>
>>> [...]
>>>> @@ -963,6 +966,56 @@ static int unpack_vectors(Vp3DecodeContext *s,
>>>> GetBitContext *gb)
>>>>    return 0;
>>>> }
>>>>
>>>> +static int unpack_block_qis(Vp3DecodeContext *s, GetBitContext  
>>>> *gb)
>>>> +{
>>>> +    int qi, i, j, bit, run_length, blocks_decoded,  
>>>> num_blocks_at_qi;
>>>> +    int num_blocks = s->coded_fragment_list_index;
>>>> +
>>>> +    for (qi = 0; qi < s->nqis-1 && num_blocks > 0; qi++) {
>>>> +        i = blocks_decoded = num_blocks_at_qi = 0;
>>>> +
>>>> +        bit = get_bits1(gb);
>>>> +
>>>> +        do {
>>>
>>>> +            run_length = get_vlc2(gb,
>>>> s->superblock_run_length_vlc.table, 6, 2);
>>>> +            if (run_length == 33)
>>>> +                run_length += get_bits(gb, 12);
>>>
>>>> +            run_length++;
>>>
>>> run_length = get_vlc2(gb, s->superblock_run_length_vlc.table, 6,  
>>> 2) + 1;
>>
>> Fixed.
>>
>>>> +            blocks_decoded += run_length;
>>>> +
>>>
>>>> +            if (bit) {
>>>> +                for (j = 0; j < run_length; i++) {
>>>> +                    if (i > s->coded_fragment_list_index)
>>>> +                        return -1;
>>>> +
>>>> +                    if (s->all_fragments[s- 
>>>> >coded_fragment_list[i]].qi
>>>> == qi) {
>>>> +
>>>> s->all_fragments[s->coded_fragment_list[i]].qi++;
>>>> +                        j++;
>>>> +                    }
>>>> +                }
>>>> +            } else {
>>>> +                num_blocks_at_qi += run_length;
>>>> +                for (j = 0; j < run_length; i++) {
>>>> +                    if (i > s->coded_fragment_list_index)
>>>> +                        return -1;
>>>> +
>>>> +                    if (s->all_fragments[s- 
>>>> >coded_fragment_list[i]].qi
>>>> == qi)
>>>> +                        j++;
>>>> +                }
>>>> +            }
>>>
>>> this could be factorized, though tht would be slower, by a hair in  
>>> theory
>>> what effect on the whole does this have speedwise?
>>
>> This loop is not executed if there's only one quant per frame  
>> (essentially
>> all Theora files in existence) and takes 1% of the decode time on the
>> sample I'm using, so I factored the two sides with no noticeable  
>> speedloss.
>>
>> The additional indirection in determining the dequant table has a  
>> 0.4%
>> slowdown however.
>>
>
>> commit 6d8bb33c99f55af808c9e349dc50c06a27c11aea
>> Author: David Conrad <lessen42 at gmail.com>
>> Date:   Thu May 28 13:30:57 2009 -0400
>>
>>    Support block-level quantization in Theora
>
> probably ok, assuming its tested

Doesn't change normal VP3/Theora, and I'm attributing the artifacts on  
interframes of theora_derf.ogg to the quant tables being stored  
incorrectly.

Applied.



More information about the ffmpeg-devel mailing list