[FFmpeg-devel] [HACK] mov.c: Handle MPEG-in-MOV (#241 and friends)

Michael Niedermayer michaelni at gmx.at
Wed Oct 17 17:48:37 CEST 2012


On Wed, Oct 17, 2012 at 05:35:11PM +0200, Petter Ericson wrote:
> On Wed, Oct 17, 2012 at 05:15:20PM +0200, Michael Niedermayer wrote:
> > On Wed, Oct 17, 2012 at 05:04:07PM +0200, Petter Ericson wrote:
> > > On Wed, Oct 17, 2012 at 02:35:07AM +0200, Michael Niedermayer wrote:
> > > > On Tue, Oct 16, 2012 at 09:33:24PM +0200, Petter Ericson wrote:
> > > > > On Tue, Oct 16, 2012 at 06:43:50PM +0200, Hendrik Leppkes wrote:
> > > > > > On Tue, Oct 16, 2012 at 5:18 PM, Petter Ericson
> > > > > > <petter.ericson at codemill.se> wrote:
> > > > > > > Greetings,
[...]
>  mov.c |   50 +++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 43 insertions(+), 7 deletions(-)
> e6c017cc3510726ce8841b29a00899812c1520a0  0001-mov.c.patch
> From dd0c50b40e7264c9c3d22b010f0f10831aede88f Mon Sep 17 00:00:00 2001
> From: Petter Ericson <petter.ericson at codemill.se>
> Date: Wed, 17 Oct 2012 16:53:19 +0200
> Subject: [PATCH] mov.c:     Check for stsd + m1s tag indicating MOV-wrapped
>  MPEG-PS, and force 	continued probing if found.
> 
> ---
>  libavformat/mov.c |   50 +++++++++++++++++++++++++++++++++++++++++++-------
>  1 file changed, 43 insertions(+), 7 deletions(-)
> 
> diff --git a/libavformat/mov.c b/libavformat/mov.c
> index b817bc9..e93356f 100644
> --- a/libavformat/mov.c
> +++ b/libavformat/mov.c
> @@ -2861,43 +2861,79 @@ static int mov_probe(AVProbeData *p)
>      unsigned int offset;
>      uint32_t tag;
>      int score = 0;

> +    int stsd = MKTAG('s','t','s','d');

thats not making the code clearar, its used just once


> +    int moov_offset = -1;
>  
>      /* check file header */
>      offset = 0;
>      for (;;) {
>          /* ignore invalid offset */
>          if ((offset + 8) > (unsigned int)p->buf_size)
> -            return score;
> +            break;
>          tag = AV_RL32(p->buf + offset + 4);
>          switch(tag) {
>          /* check for obvious tags */
> -        case MKTAG('j','P',' ',' '): /* jpeg 2000 signature */
>          case MKTAG('m','o','o','v'):
> +            moov_offset = offset + 4;
> +        case MKTAG('j','P',' ',' '): /* jpeg 2000 signature */
>          case MKTAG('m','d','a','t'):
>          case MKTAG('p','n','o','t'): /* detect movs with preview pics like ew.mov and april.mov */
>          case MKTAG('u','d','t','a'): /* Packet Video PVAuthor adds this and a lot of more junk */
>          case MKTAG('f','t','y','p'):
> -            return AVPROBE_SCORE_MAX;
> +            score = FFMAX(score, AVPROBE_SCORE_MAX);
> +            offset = AV_RB32(p->buf+offset) + offset;
> +            break;
>          /* those are more common words, so rate then a bit less */
>          case MKTAG('e','d','i','w'): /* xdcam files have reverted first tags */
>          case MKTAG('w','i','d','e'):
>          case MKTAG('f','r','e','e'):
>          case MKTAG('j','u','n','k'):
>          case MKTAG('p','i','c','t'):
> -            return AVPROBE_SCORE_MAX - 5;
> +            score = FFMAX(score, AVPROBE_SCORE_MAX - 5);
> +            offset = AV_RB32(p->buf+offset) + offset;

that can end in a infinite loop if the read value is 0


> +            break;
>          case MKTAG(0x82,0x82,0x7f,0x7d):
>          case MKTAG('s','k','i','p'):
>          case MKTAG('u','u','i','d'):
>          case MKTAG('p','r','f','l'):
>              offset = AV_RB32(p->buf+offset) + offset;
>              /* if we only find those cause probedata is too small at least rate them */
> -            score = AVPROBE_SCORE_MAX - 50;
> +            score = FFMAX(score, AVPROBE_SCORE_MAX - 50);
>              break;
>          default:
> -            /* unrecognized tag */
> -            return score;
> +            offset = AV_RB32(p->buf + offset) + offset ;
>          }
>      }
> +    if(tag > AVPROBE_SCORE_MAX - 50 && moov_offset != -1){
> +        /* We should make sure that this is not a MOV-packed MPEG-PS */
> +        offset = moov_offset;
> +        
> +        while(offset < (p->buf_size - 20) && /* Sufficient space */
> +              AV_RL32(p->buf+offset) != stsd)
> +            offset++;
> +
> +
> +        /* We didn't find an stsd atom for some reason */
> +        if(offset == (p->buf_size - 20))
> +            return score;
> +
> +        /* Make sure there's only one stream */
> +        if(AV_RB32(p->buf + offset + 8) != 1) 
> +            return score;
> +
> +        /* Check for m1s tag */
> +        if(AV_RL32(p->buf + offset + 16) != MKTAG('m','1','s',' '))
> +            return score;

this would fail if by sheer (bad) luck the string "stsd" would occur
before the correct stsd, this is not nearly as unlikely as it seems
its ascii, and there might be some kind of metadata in the headers
that too is ascii ...

all the checks should be done together, that is
while(foo){
    if(we have stsd && one stream && m1s)
        return 5;
}

[...]


-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Asymptotically faster algorithms should always be preferred if you have
asymptotical amounts of data
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 198 bytes
Desc: Digital signature
URL: <http://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20121017/4b75d66c/attachment.asc>


More information about the ffmpeg-devel mailing list