[FFmpeg-devel] [PATCH] png parser
    Peter Holik 
    peter
       
    Wed Jun 24 17:54:17 CEST 2009
    
    
  
Michael Niedermayer schrieb:
> On Tue, Jun 23, 2009 at 08:51:12AM +0200, Peter Holik wrote:
>> Michael Niedermayer schrieb:
> [...]
>
>> +static int png_parse(AVCodecParserContext *s, AVCodecContext *avctx,
>> +                     const uint8_t **poutbuf, int *poutbuf_size,
>> +                     const uint8_t *buf, int buf_size)
>> +{
>> +    PNGParseContext *ppc = s->priv_data;
>> +    uint32_t *state_ptr;
>> +    int next = END_NOT_FOUND;
>> +    int i = 0;
>> +
>> +    *poutbuf_size = 0;
>> +    if (buf_size == 0)
>> +        return 0;
>> +
>> +    if (!ppc->pc.frame_start_found) {
>> +        uint64_t *state64_ptr = &ppc->pc.state64;
>> +
>> +        for (; i < buf_size; i++) {
>> +            *state64_ptr = (*state64_ptr << 8) | buf[i];
>
> using a local state64 likely is faster than the repeated pointer deref
> i suspect gcc fails to do that optim itself ...
done.
>> +            if (*state64_ptr == PNGSIG || *state64_ptr == MNGSIG) {
>> +                i++;
>> +                if (ppc->pc.index) {
>> +                    i -= 8;
>> +                    next = i;
>> +                } else {
>> +                    ppc->pc.frame_start_found = 1;
>> +                    ppc->chunk_index = 1;
>> +                    if (i == 8)
>> +                        break;
>> +                    else if (i > 8) {
>> +                        buf += i - 8;
>> +                        buf_size = 8;
>> +                    } else /* if (i < 8) */
>> +                        buf_size = i;
>> +                }
>> +                ff_combine_frame(&ppc->pc, next, &buf, &buf_size);
>> +                return i;
>
> could you explain why this is not just looking like lets say mpeg4:
>
>     if(!vop_found){
>         for(i=0; i<buf_size; i++){
>             state= (state<<8) | buf[i];
>             if(state == 0x1B6){
>                 i++;
>                 vop_found=1;
>                 break;
>             }
>         }
>     }
png signature is 8 Bytes
> what is the point of all the special cases?
Because this png parser should filter out good png images.
1. Case
Usually you get a buf starting with a png signature, therefor "i" would be 8
and i skip any special handling.
2. Case
There are some headerbytes at the beginning, that i will drop:
        else if (i > 8) {
              buf += i - 8;
              buf_size = 8;
        ff_combine_frame(&ppc->pc, next, &buf, &buf_size);
        return i;
here i copy the read signature into my buffer with ff_combine_frame
(and modified buf to start from signature start)
3. Case
The signature starts in the next buf:
the first buf is copied to my buffer with ff_combine_frame
for the next one i know it - ppc->pc.index != NULL
        if (ppc->pc.index) {
               i -= 8;
               next = i;
        ff_combine_frame(&ppc->pc, next, &buf, &buf_size);
        return i;
and finish my buffer and return, that i have read till to the start of png signature
the next time png_parse is called with a buf starting with a png signature
like 1. Case
4. Case
The signature ends in the next buf and starts in the first buf:
the first buf is copied to my buffer with ff_combine_frame
for the next one i know it - ppc->pc.index != NULL
        if (ppc->pc.index) {
               i -= 8;
               next = i;
        ff_combine_frame(&ppc->pc, next, &buf, &buf_size);
        return i;
But now "next is NEGATIVE"!
i finish my buffer with ff_combine_frame and return a minus value
(that is set to 0 in av_parser_parse2)
now the magic of "ff_combine_frame" - a negative next means "overread"
ff_combine_frame does
for(;next < 0; next++) pc->overread++;
next time png_parse is called with the same buf and "i" would be < 8
 } else /* if (i < 8) */
    buf_size = i;
  ff_combine_frame(&ppc->pc, next, &buf, &buf_size);
  return i;
this time ff_combine_frame fills my buffer with parts of the overread png signature
/* Copy overread bytes from last frame into buffer. */
    for(; pc->overread>0; pc->overread--){
        pc->buffer[pc->index++]= pc->buffer[pc->overread_index++];
    }
and copies the rest of the signature into my buffer.
next time png_parse is called buf starts after the png signature
cu Peter
-------------- next part --------------
A non-text attachment was scrubbed...
Name: png_parser.diff
Type: text/x-diff
Size: 5779 bytes
Desc: not available
URL: <http://lists.mplayerhq.hu/pipermail/ffmpeg-devel/attachments/20090624/bc91c45e/attachment.diff>
    
    
More information about the ffmpeg-devel
mailing list