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

Tomas Härdin tomas.hardin at codemill.se
Fri Oct 19 10:32:26 CEST 2012


> From d5c1223d03dd8147d04b53a59ef655e9d87af129 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 |   45 +++++++++++++++++++++++++++++++++++++--------
>  1 file changed, 37 insertions(+), 8 deletions(-)
> 
> diff --git a/libavformat/mov.c b/libavformat/mov.c
> index b817bc9..8899227 100644
> --- a/libavformat/mov.c
> +++ b/libavformat/mov.c
> @@ -2861,43 +2861,72 @@ static int mov_probe(AVProbeData *p)
>      unsigned int offset;
>      uint32_t tag;
>      int score = 0;
> +    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);

score = AVPROBE_SCORE_MAX; is enough

> +            offset = FFMAX(1, (unsigned int)AV_RB32(p->buf+offset)) + offset;

You could/should change the 1 to a 4
AV_RB32() is unsigned, so the cast is useless.

> +            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 = FFMAX(1, AV_RB32(p->buf+offset)) + offset;

1 -> 4

> +            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);
> +            offset = FFMAX(1, AV_RB32(p->buf+offset)) + offset;

1 -> 4

>              break;
>          default:
> -            /* unrecognized tag */
> -            return score;
> +            offset = FFMAX(1, AV_RB32(p->buf+offset)) + offset;

1 -> 4

> +        }
> +    }
> +    if(tag > AVPROBE_SCORE_MAX - 50 && moov_offset != -1){

nit: if (...) {

> +        /* moov atom in the header - we should make sure that this is not a
> +         * MOV-packed MPEG-PS */
> +        offset = moov_offset;
> +        
> +        while(offset < (p->buf_size - 20)){ /* Sufficient space */
> +               /* We found an actual stsd atom */
> +            if(AV_RL32(p->buf+offset)       == MKTAG('s','t','s','d') &&
> +               /* Make sure there's only one stream */
> +               AV_RB32(p->buf + offset + 8)  == 1 &&
> +               AV_RL32(p->buf + offset + 16) == MKTAG('m','1','s',' ')
> +               ){
> +                av_log(NULL, AV_LOG_WARNING, "Found m1s tag indicating this is a MOV-packed MPEG-PS.\n");
> +                /* We found an stsd atom describing an MPEG-PS-in-MOV, return a
> +                 * low score to force expanding the probe window until
> +                 * mpegps_probe finds what it needs */
> +                return 5;
> +            }else
> +                /* Keep looking */
> +                offset++;

IIRC MOV mandates two-byte alignment. offset += 2; would speed this up.

Looks reasonable, apart from formatting nitpickery.

I wonder, is there any risk PROBE_BUF_MIN might be changed in the
future? This will stop working if PROBE_BUF_MIN is ever changed to
something less than 0x222. A check like the following might be in order:

#if PROBE_BUF_MIN < 0x222
#error Too small PROBE_BUF_MIN to deal with m1s MOVs
#endif

/Tomas



More information about the ffmpeg-devel mailing list