[FFmpeg-devel] [PATCH] CCITT Group 3 and 4 decompression

Michael Niedermayer michaelni
Thu Dec 25 19:33:35 CET 2008


On Thu, Dec 25, 2008 at 08:19:25AM +0200, Kostya wrote:
> On Wed, Dec 24, 2008 at 11:00:08PM +0100, Michael Niedermayer wrote:
> > On Wed, Dec 24, 2008 at 08:06:13AM +0200, Kostya wrote:
> > > On Tue, Dec 23, 2008 at 08:27:31PM +0100, Michael Niedermayer wrote:
> > > > On Tue, Dec 23, 2008 at 09:00:57AM +0200, Kostya wrote:
> > > > > On Mon, Dec 22, 2008 at 09:06:37PM +0100, Michael Niedermayer wrote:
> > > > > > On Mon, Dec 22, 2008 at 08:15:06PM +0200, Kostya wrote:
> > > > > > > On Mon, Dec 22, 2008 at 01:13:53PM +0100, Michael Niedermayer wrote:
> > > > > > > > On Mon, Dec 22, 2008 at 08:31:55AM +0200, Kostya wrote:
> > > > > > > > > I need that for resolving issue 750 on roundup.
[...]

> > > +static int find_group3_syncmarker(GetBitContext *gb, int srcsize)
> > > +{
> > > +    int state = get_bits(gb, 12);
> > > +    int rem = srcsize - get_bits_count(gb);
> > > +    while((state & 0xFFF) != 1){
> > > +        state = (state << 1) | get_bits1(gb);
> > > +        if(--rem <= 0)
> > > +            return -1;
> > > +    }
> > > +    return 0;
> > > +}
> > 
> > you only need 1 get_bits call in this function
> > besides this code is buggy, it will miss the sync code when its at
> > the end, that is it will never check the last read bit
> > Ive already provided a working implementation, why dont you use it?
> 

> In most cases EOL will follow line data immediately, so the loop won't
> be entered at all instead of 12 iterations in your case. 

it really doesnt matter speedwise, this code isnt executed often enough
but if its important for you, leave it there.


> Also it does
> not matter for decoding if there's EOL right one bit before line end -
> there won't be sufficient data to decode that line anyway (for 2d-case
> that single bit is read to determine line coding mode and for 1d case
> first codeword should have length >= 4 bits).

its imporant to detect errors, for that it is important to find out if
a sync marker is missing, this also includes the last sync marker.

i can offer to cleanup, commit and maintain CCITT fax support myself if
you dont want to fix the issues?

[...]
> > btw, do you have some url where i can find files to test this code?
> 
> http://samples.mplayerhq.hu/image-samples/tiff/
>  

thanks


> > PS: merry christmas :)
> 
> Well, I live in a country where church calendar uses incorrect rounding
> and was tied to the standard one only in XXth century with 13 days of difference
> we have New Year first, then Christmas on Jan 7th and then Old New Year on
> Jan 14th (i.e.  New Year in Old calendar). Pretty amusing, eh?

a few days off isnt that bad ...
keep in mind that the whole calendar the world is using is a few years off,
wiki says something between 2 and 7 years.


[...]
> @@ -103,6 +105,26 @@
>              return -1;
>          }
>      }
> +    if(s->compr == TIFF_CCITT_RLE || s->compr == TIFF_G3 || s->compr == TIFF_G4){
> +        int i, ret = 0;
> +        uint8_t *src2 = av_malloc(size);
> +
> +        for(i = 0; i < size; i++)
> +            src2[i] = ff_reverse[src[i]];

out of mem check missing


[...]
> +static int decode_group3_1d_line(AVCodecContext *avctx, GetBitContext *gb,
> +                                 int pix_left, int *runs)
> +{
> +    int mode = 0, run = 0;
> +    unsigned int t;
> +    for(;;){
> +        t = get_vlc2(gb, ccitt_vlc[mode].table, 9, 2);
> +        run += t;
> +        if(t < 64){

first


> +            pix_left -= run;
> +            *runs++ = run;

> +            if(!pix_left){

second


> +                break;
> +            }else if(pix_left < 0){

third

still 3

its really easy to just merge the 2nd and 3rd

if(pix_left <= 0){
    if(!pix_left)
        break;
    ...
}

just think of how often each side is true

if(!pix_left)     true maximally once at the end of a undamaged line
if(pix_left<0)    true maximally once in case of an overrun of a damaged line

while the code in the if(t<64) branch is executed once per run, and there
can be 1 run per pixel, thats for a 1024x768 image 1024 times more
often (in worst case) and still equally often if you encode just a empty
white page

if you write
if(!pix_left){
...
else if(pix_left < 0){

then there are 2 if() that is 2 for each run has to be checked

if you write 

if(pix_left <= 0){
    if(!pix_left)
        break;
    ...
}

there are just half as many

also, what about runs of 0 ?
if they are not allowed (except at pos 0) that should be checked for and an
error be printed. Its easy to check for 0 before the loop and remove the 0
code from the table ...
Alternatively, if 0 is allowed at any place that should be supported, iam
not sure if it is currently ...

[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

If a bugfix only changes things apparently unrelated to the bug with no
further explanation, that is a good sign that the bugfix is wrong.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 189 bytes
Desc: Digital signature
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20081225/ba9f8591/attachment.pgp>



More information about the ffmpeg-devel mailing list