Ignore:
Timestamp:
Nov 20, 2006, 9:45:29 PM (18 years ago)
Author:
vladest
Message:

FFMPEG update
significal changes - avi/mpegts/mpegps now handled by ffmpeg demuxer. From my point of view it works much more corrdctly

File:
1 edited

Legend:

Unmodified
Added
Removed
  • TabularUnified trunk/libmpdemux/demux_mov.c

    r181 r263  
    3131#include "stheader.h"
    3232
     33#include "subreader.h"
     34
     35extern subtitle* vo_sub;
     36int vo_osd_changed(int new_value);
     37#define OSDTYPE_OSD 1
     38#define OSDTYPE_SUBTITLE 2
     39#define OSDTYPE_PROGBAR 3
     40#define OSDTYPE_SPU 4
     41
    3342#include "bswap.h"
    3443
     
    5362
    5463#define BE_16(x) (((unsigned char *)(x))[0] <<  8 | \
    55                   ((unsigned char *)(x))[1])
     64    ((unsigned char *)(x))[1])
    5665#define BE_32(x) (((unsigned char *)(x))[0] << 24 | \
    57                   ((unsigned char *)(x))[1] << 16 | \
    58                   ((unsigned char *)(x))[2] <<  8 | \
    59                   ((unsigned char *)(x))[3])
     66    ((unsigned char *)(x))[1] << 16 | \
     67    ((unsigned char *)(x))[2] <<  8 | \
     68    ((unsigned char *)(x))[3])
    6069
    6170#define char2short(x,y) BE_16(&(x)[(y)])
     
    164173    if (trak->chunks_size <= 0)
    165174    {
    166         dprintf(MSGT_DEMUX,  "No chunk offset table, trying to build one!\n");
    167 
    168         trak->chunks_size = trak->samples_size; /* XXX: FIXME ! */
    169         trak->chunks = realloc(trak->chunks, sizeof(mov_chunk_t)*trak->chunks_size);
    170 
    171         for (i=0; i < trak->chunks_size; i++)
    172             trak->chunks[i].pos = -1;
     175        dprintf(MSGT_DEMUX,  "No chunk offset table, trying to build one!\n");
     176
     177        trak->chunks_size = trak->samples_size; /* XXX: FIXME ! */
     178        trak->chunks = realloc(trak->chunks, sizeof(mov_chunk_t)*trak->chunks_size);
     179
     180        for (i=0; i < trak->chunks_size; i++)
     181            trak->chunks[i].pos = -1;
    173182    }
    174183#endif
     
    180189    i=trak->chunkmap_size;
    181190    while(i>0){
    182         --i;
    183         for(j=trak->chunkmap[i].first;j<last;j++){
    184             trak->chunks[j].desc=trak->chunkmap[i].sdid;
    185             trak->chunks[j].size=trak->chunkmap[i].spc;
    186         }
    187         last=trak->chunkmap[i].first;
     191        --i;
     192        for(j=trak->chunkmap[i].first;j<last;j++){
     193            trak->chunks[j].desc=trak->chunkmap[i].sdid;
     194            trak->chunks[j].size=trak->chunkmap[i].spc;
     195        }
     196        last=trak->chunkmap[i].first;
    188197    }
    189198
     
    191200    for (i=0; i < trak->chunks_size; i++)
    192201    {
    193         /* fixup position */
    194         if (trak->chunks[i].pos == -1)
    195             if (i > 0)
    196                 trak->chunks[i].pos = trak->chunks[i-1].pos + trak->chunks[i-1].size;
    197             else
    198                 trak->chunks[i].pos = 0; /* FIXME: set initial pos */
     202        /* fixup position */
     203        if (trak->chunks[i].pos == -1)
     204            if (i > 0)
     205                trak->chunks[i].pos = trak->chunks[i-1].pos + trak->chunks[i-1].size;
     206            else
     207                trak->chunks[i].pos = 0; /* FIXME: set initial pos */
    199208#endif
    200209
    201     // calc pts of chunks:
    202     s=0;
    203     for(j=0;j<trak->chunks_size;j++){
    204         trak->chunks[j].sample=s;
    205         s+=trak->chunks[j].size;
     210        // calc pts of chunks:
     211        s=0;
     212        for(j=0;j<trak->chunks_size;j++){
     213            trak->chunks[j].sample=s;
     214            s+=trak->chunks[j].size;
     215        }
     216        i = 0;
     217        for (j = 0; j < trak->durmap_size; j++)
     218            i += trak->durmap[j].num;
     219        if (i != s) {
     220            dprintf("MOV: durmap and chunkmap sample count differ (%i vs %i)\n", i, s);
     221            if (i > s) s = i;
     222        }
     223
     224        // workaround for fixed-size video frames (dv and uncompressed)
     225        if(!trak->samples_size && trak->type!=MOV_TRAK_AUDIO){
     226            trak->samples_size=s;
     227            trak->samples=calloc(s, sizeof(mov_sample_t));
     228            for(i=0;i<s;i++)
     229                trak->samples[i].size=trak->samplesize;
     230            trak->samplesize=0;
     231        }
     232
     233        if(!trak->samples_size){
     234            // constant sampesize
     235            if(trak->durmap_size==1 || (trak->durmap_size==2 && trak->durmap[1].num==1)){
     236                trak->duration=trak->durmap[0].dur;
     237            } else dprintf("*** constant samplesize & variable duration not yet supported! ***\nContact the author if you have such sample file!\n");
     238            return;
     239        }
     240
     241        if (trak->samples_size < s) {
     242            dprintf("MOV: durmap or chunkmap bigger than sample count (%i vs %i)\n",
     243                    s, trak->samples_size);
     244            trak->samples_size = s;
     245            trak->samples = realloc_struct(trak->samples, s, sizeof(mov_sample_t));
     246        }
     247
     248        // calc pts:
     249        s=0;
     250        for(j=0;j<trak->durmap_size;j++){
     251            for(i=0;i<trak->durmap[j].num;i++){
     252                trak->samples[s].pts=pts;
     253                ++s;
     254                pts+=trak->durmap[j].dur;
     255            }
     256        }
     257
     258        // calc sample offsets
     259        s=0;
     260        for(j=0;j<trak->chunks_size;j++){
     261            off_t pos=trak->chunks[j].pos;
     262            for(i=0;i<trak->chunks[j].size;i++){
     263                trak->samples[s].pos=pos;
     264                dprintf( "Sample %5d: pts=%8d  off=0x%08X  size=%d\n",s,
     265                        trak->samples[s].pts,
     266                        (int)trak->samples[s].pos,
     267                        trak->samples[s].size);
     268                pos+=trak->samples[s].size;
     269                ++s;
     270            }
     271        }
     272
     273        // precalc editlist entries
     274        if(trak->editlist_size>0){
     275            int frame=0;
     276            int e_pts=0;
     277            for(i=0;i<trak->editlist_size;i++){
     278                mov_editlist_t* el=&trak->editlist[i];
     279                int sample=0;
     280                int pts=el->pos;
     281                el->start_frame=frame;
     282                if(pts<0){
     283                    // skip!
     284                    el->frames=0; continue;
     285                }
     286                // find start sample
     287                for(;sample<trak->samples_size;sample++){
     288                    if(pts<=trak->samples[sample].pts) break;
     289                }
     290                el->start_sample=sample;
     291                el->pts_offset=((long long)e_pts*(long long)trak->timescale)/(long long)timescale-trak->samples[sample].pts;
     292                pts+=((long long)el->dur*(long long)trak->timescale)/(long long)timescale;
     293                e_pts+=el->dur;
     294                // find end sample
     295                for(;sample<trak->samples_size;sample++){
     296                    if(pts<trak->samples[sample].pts) break;
     297                }
     298                el->frames=sample-el->start_sample;
     299                frame+=el->frames;
     300                dprintf("EL#%d: pts=%d  1st_sample=%d  frames=%d (%5.3fs)  pts_offs=%d\n",i,
     301                        el->pos,el->start_sample, el->frames,
     302                        (float)(el->dur)/(float)timescale, el->pts_offset);
     303            }
     304        }
    206305    }
    207     i = 0;
    208     for (j = 0; j < trak->durmap_size; j++)
    209       i += trak->durmap[j].num;
    210     if (i != s) {
    211       dprintf(
    212              "MOV: durmap and chunkmap sample count differ (%i vs %i)\n", i, s);
    213       if (i > s) s = i;
     306
     307#define MOV_MAX_TRACKS 256
     308#define MOV_MAX_SUBLEN 1024
     309
     310    typedef struct {
     311        off_t moov_start;
     312        off_t moov_end;
     313        off_t mdat_start;
     314        off_t mdat_end;
     315        int track_db;
     316        mov_track_t* tracks[MOV_MAX_TRACKS];
     317        int timescale; // movie timescale
     318        int duration;  // movie duration (in movie timescale units)
     319        subtitle subs;
     320        char subtext[MOV_MAX_SUBLEN + 1];
     321        int current_sub;
     322    } mov_priv_t;
     323
     324#define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d))
     325
     326    static int mov_check_file(demuxer_t* demuxer){
     327        int flags=0;
     328        int no=0;
     329        mov_priv_t* priv=malloc(sizeof(mov_priv_t));
     330
     331        dprintf("Checking for MOV\n");
     332
     333        memset(priv,0,sizeof(mov_priv_t));
     334        priv->current_sub = -1;
     335
     336        while(1){
     337            int i;
     338            int skipped=8;
     339            off_t len=stream_read_dword(demuxer->stream);
     340            unsigned int id=stream_read_dword(demuxer->stream);
     341            if(stream_eof(demuxer->stream)) break; // EOF
     342            if (len == 1) /* real size is 64bits - cjb */
     343            {
     344#ifndef _LARGEFILE_SOURCE
     345                if (stream_read_dword(demuxer->stream) != 0)
     346                    dprintf( "64bit file, but you've compiled MPlayer without LARGEFILE support!\n");
     347                len = stream_read_dword(demuxer->stream);
     348#else
     349                len = stream_read_qword(demuxer->stream);
     350#endif
     351                skipped += 8;
     352            }
     353#if 0
     354            else if (len == 0) /* deleted chunk */
     355            {
     356                /* XXX: CJB! is this right? - alex */
     357                goto skip_chunk;
     358            }
     359#endif
     360            else if(len<8) break; // invalid chunk
     361
     362            switch(id){
     363            case MOV_FOURCC('f','t','y','p'): {
     364                unsigned int tmp;
     365                // File Type Box (ftyp):
     366                // char[4]  major_brand    (eg. 'isom')
     367                // int      minor_version          (eg. 0x00000000)
     368                // char[4]  compatible_brands[]  (eg. 'mp41')
     369                // compatible_brands list spans to the end of box
     370#if 1
     371                tmp = stream_read_dword(demuxer->stream);
     372                switch(tmp) {
     373                case MOV_FOURCC('i','s','o','m'):
     374                    dprintf("ISO: File Type Major Brand: ISO Base Media\n");
     375                    break;
     376                case MOV_FOURCC('m','p','4','1'):
     377                    dprintf("ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v1\n");
     378                    break;
     379                case MOV_FOURCC('m','p','4','2'):
     380                    dprintf("ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v2\n");
     381                    break;
     382                case MOV_FOURCC('M','4','A',' '):
     383                    dprintf("ISO: File Type Major Brand: Apple iTunes AAC-LC Audio\n");
     384                    break;
     385                case MOV_FOURCC('M','4','P',' '):
     386                    dprintf("ISO: File Type Major Brand: Apple iTunes AAC-LC Protected Audio\n");
     387                    break;
     388                case MOV_FOURCC('q','t',' ',' '):
     389                    dprintf("ISO: File Type Major Brand: Original QuickTime\n");
     390                    break;
     391                case MOV_FOURCC('3','g','p','1'):
     392                    dprintf("ISO: File Type Major Brand: 3GPP Profile 1\n");
     393                    break;
     394                case MOV_FOURCC('3','g','p','2'):
     395                case MOV_FOURCC('3','g','2','a'):
     396                    dprintf("ISO: File Type Major Brand: 3GPP Profile 2\n");
     397                    break;
     398                case MOV_FOURCC('3','g','p','3'):
     399                    dprintf("ISO: File Type Major Brand: 3GPP Profile 3\n");
     400                    break;
     401                case MOV_FOURCC('3','g','p','4'):
     402                    dprintf("ISO: File Type Major Brand: 3GPP Profile 4\n");
     403                    break;
     404                case MOV_FOURCC('3','g','p','5'):
     405                    dprintf("ISO: File Type Major Brand: 3GPP Profile 5\n");
     406                    break;
     407                case MOV_FOURCC('m','m','p','4'):
     408                    dprintf("ISO: File Type Major Brand: Mobile ISO/IEC 14496-1 (MPEG-4 system)\n");
     409                    break;
     410                default:
     411                    tmp = be2me_32(tmp);
     412                    dprintf("ISO: Unknown File Type Major Brand: %.4s\n",(char *)&tmp);
     413                }
     414                dprintf("ISO: File Type Minor Version: %d\n",
     415                        stream_read_dword(demuxer->stream));
     416                skipped += 8;
     417                // List all compatible brands
     418                for(i = 0; i < ((len-16)/4); i++) {
     419                    tmp = be2me_32(stream_read_dword(demuxer->stream));
     420                    dprintf("ISO: File Type Compatible Brand #%d: %.4s\n",i,(char *)&tmp);
     421                    skipped += 4;
     422                }
     423#endif
     424            } break;
     425            case MOV_FOURCC('m','o','o','v'):
     426                //      case MOV_FOURCC('c','m','o','v'):
     427                dprintf("MOV: Movie header found!\n");
     428                priv->moov_start=(off_t)stream_tell(demuxer->stream);
     429                priv->moov_end=(off_t)priv->moov_start+len-skipped;
     430                dprintf("MOV: Movie header: start: %"PRIx64" end: %"PRIx64"\n",
     431                        (int64_t)priv->moov_start, (int64_t)priv->moov_end);
     432                skipped+=8;
     433                i = stream_read_dword(demuxer->stream)-8;
     434                if(stream_read_dword(demuxer->stream)==MOV_FOURCC('r','m','r','a')){
     435                    int ref=0;
     436                    skipped+=i;
     437                    dprintf("MOV: Reference Media file!!!\n");
     438                    //set demuxer type to playlist ...
     439                    demuxer->type=DEMUXER_TYPE_PLAYLIST;
     440                    while(i>0){
     441                        int len=stream_read_dword(demuxer->stream)-8;
     442                        int fcc=stream_read_dword(demuxer->stream);
     443                        if(len<0) break; // EOF!?
     444                        i-=8;
     445                        //                printf("i=%d  len=%d\n",i,len);
     446                        switch(fcc){
     447                        case MOV_FOURCC('r','m','d','a'):
     448                            continue;
     449                        case MOV_FOURCC('r','d','r','f'): {
     450                            int tmp=stream_read_dword(demuxer->stream);
     451                            int type=stream_read_dword_le(demuxer->stream);
     452                            int slen=stream_read_dword(demuxer->stream);
     453                            //char* s=malloc(slen+1);
     454                            //stream_read(demuxer->stream,s,slen);
     455
     456                            //FIXME: also store type & data_rate ?
     457                            ds_read_packet(demuxer->video,
     458                                           demuxer->stream,
     459                                           slen,
     460                                           0,
     461                                           stream_tell(demuxer->stream),
     462                                           0 // no flags
     463                                          );
     464                            flags|=4;
     465                            dprintf("Added reference to playlist\n");
     466                            //s[slen]=0;
     467                            //dprintf("REF: [%.4s] %s\n",&type,s);
     468                            len-=12+slen;i-=12+slen; break;
     469                        }
     470                        case MOV_FOURCC('r','m','d','r'): {
     471                            int flags=stream_read_dword(demuxer->stream);
     472                            int rate=stream_read_dword(demuxer->stream);
     473                            dprintf("  min. data rate: %d bits/sec\n",rate);
     474                            len-=8; i-=8; break;
     475                        }
     476                        case MOV_FOURCC('r','m','q','u'): {
     477                            int q=stream_read_dword(demuxer->stream);
     478                            dprintf("  quality index: %d\n",q);
     479                            len-=4; i-=4; break;
     480                        }
     481                        }
     482                        i-=len;stream_skip(demuxer->stream,len);
     483                    }
     484                }
     485                flags|=1;
     486                break;
     487            case MOV_FOURCC('w','i','d','e'):
     488                dprintf("MOV: 'WIDE' chunk found!\n");
     489                if(flags&2) break;
     490            case MOV_FOURCC('m','d','a','t'):
     491                dprintf("MOV: Movie DATA found!\n");
     492                priv->mdat_start=stream_tell(demuxer->stream);
     493                priv->mdat_end=priv->mdat_start+len-skipped;
     494                dprintf("MOV: Movie data: start: %"PRIx64" end: %"PRIx64"\n",
     495                        (int64_t)priv->mdat_start, (int64_t)priv->mdat_end);
     496                flags|=2;
     497                if(flags==3){
     498                    // if we're over the headers, then we can stop parsing here!
     499                    demuxer->priv=priv;
     500                    return DEMUXER_TYPE_MOV;
     501                }
     502                break;
     503            case MOV_FOURCC('f','r','e','e'):
     504            case MOV_FOURCC('s','k','i','p'):
     505            case MOV_FOURCC('j','u','n','k'):
     506                dprintf("MOV: free space (len: %"PRId64")\n", (int64_t)len);
     507                /* unused, if you edit a mov, you can use space provided by free atoms (redefining it) */
     508                break;
     509            case MOV_FOURCC('p','n','o','t'):
     510            case MOV_FOURCC('P','I','C','T'):
     511                /* dunno what, but we shoudl ignore it */
     512                break;
     513            default:
     514                if(no==0){ free(priv); return 0;} // first chunk is bad!
     515                id = be2me_32(id);
     516                dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
     517            }
     518        skip_chunk:
     519            if(!stream_skip(demuxer->stream,len-skipped)) break;
     520            ++no;
     521        }
     522
     523        if(flags==3){
     524            demuxer->priv=priv;
     525            return DEMUXER_TYPE_MOV;
     526        }
     527        free(priv);
     528
     529        if ((flags==5) || (flags==7)) // reference & header sent
     530            return DEMUXER_TYPE_PLAYLIST;
     531
     532        if(flags==1)
     533            dprintf("MOV: missing data (mdat) chunk! Maybe broken file...\n");
     534        else if(flags==2)
     535            dprintf("MOV: missing header (moov/cmov) chunk! Maybe broken file...\n");
     536
     537        return 0;
    214538    }
    215539
    216     // workaround for fixed-size video frames (dv and uncompressed)
    217     if(!trak->samples_size && trak->type!=MOV_TRAK_AUDIO){
    218         trak->samples_size=s;
    219         trak->samples=calloc(s, sizeof(mov_sample_t));
    220         for(i=0;i<s;i++)
    221             trak->samples[i].size=trak->samplesize;
    222         trak->samplesize=0;
     540    static void demux_close_mov(demuxer_t *demuxer) {
     541        mov_priv_t* priv = demuxer->priv;
     542        int i;
     543        if (!priv)
     544            return;
     545        for (i = 0; i < MOV_MAX_TRACKS; i++) {
     546            mov_track_t *track = priv->tracks[i];
     547            if (track) {
     548                free(track->tkdata);
     549                free(track->stdata);
     550                free(track->stream_header);
     551                free(track->samples);
     552                free(track->chunks);
     553                free(track->chunkmap);
     554                free(track->durmap);
     555                free(track->keyframes);
     556                free(track->editlist);
     557                free(track->desc);
     558                free(track);
     559            }
     560        }
     561        free(priv);
    223562    }
    224563
    225     if(!trak->samples_size){
    226         // constant sampesize
    227         if(trak->durmap_size==1 || (trak->durmap_size==2 && trak->durmap[1].num==1)){
    228             trak->duration=trak->durmap[0].dur;
    229         } else dprintf( "*** constant samplesize & variable duration not yet supported! ***\nContact the author if you have such sample file!\n");
    230         return;
     564    unsigned int store_ughvlc(unsigned char *s, unsigned int v){
     565        unsigned int n = 0;
     566
     567        while(v >= 0xff) {
     568            *s++ = 0xff;
     569            v -= 0xff;
     570            n++;
     571        }
     572        *s = v;
     573        n++;
     574
     575        return n;
    231576    }
    232577
    233     if (trak->samples_size < s) {
    234       dprintf(
    235              "MOV: durmap or chunkmap bigger than sample count (%i vs %i)\n",
    236              s, trak->samples_size);
    237       trak->samples_size = s;
    238       trak->samples = realloc_struct(trak->samples, s, sizeof(mov_sample_t));
     578    static void init_vobsub(sh_sub_t *sh, mov_track_t *trak) {
     579        int i;
     580        uint8_t *pal = trak->stdata;
     581        sh->type = 'v';
     582        if (trak->stdata_len < 106)
     583            return;
     584        sh->has_palette = 1;
     585        pal += 42;
     586        for (i = 0; i < 16; i++) {
     587            sh->palette[i] = BE_32(pal);
     588            pal += 4;
     589        }
    239590    }
    240 
    241     // calc pts:
    242     s=0;
    243     for(j=0;j<trak->durmap_size;j++){
    244         for(i=0;i<trak->durmap[j].num;i++){
    245             trak->samples[s].pts=pts;
    246             ++s;
    247             pts+=trak->durmap[j].dur;
    248         }
    249     }
    250 
    251     // calc sample offsets
    252     s=0;
    253     for(j=0;j<trak->chunks_size;j++){
    254         off_t pos=trak->chunks[j].pos;
    255         for(i=0;i<trak->chunks[j].size;i++){
    256             trak->samples[s].pos=pos;
    257             dprintf( "Sample %5d: pts=%8d  off=0x%08X  size=%d\n",s,
    258                 trak->samples[s].pts,
    259                 (int)trak->samples[s].pos,
    260                 trak->samples[s].size);
    261             pos+=trak->samples[s].size;
    262             ++s;
    263         }
    264     }
    265 
    266     // precalc editlist entries
    267     if(trak->editlist_size>0){
    268         int frame=0;
    269         int e_pts=0;
    270         for(i=0;i<trak->editlist_size;i++){
    271             mov_editlist_t* el=&trak->editlist[i];
    272             int sample=0;
    273             int pts=el->pos;
    274             el->start_frame=frame;
    275             if(pts<0){
    276                 // skip!
    277                 el->frames=0; continue;
    278             }
    279             // find start sample
    280             for(;sample<trak->samples_size;sample++){
    281                 if(pts<=trak->samples[sample].pts) break;
    282             }
    283             el->start_sample=sample;
    284             el->pts_offset=((long long)e_pts*(long long)trak->timescale)/(long long)timescale-trak->samples[sample].pts;
    285             pts+=((long long)el->dur*(long long)trak->timescale)/(long long)timescale;
    286             e_pts+=el->dur;
    287             // find end sample
    288             for(;sample<trak->samples_size;sample++){
    289                 if(pts<trak->samples[sample].pts) break;
    290             }
    291             el->frames=sample-el->start_sample;
    292             frame+=el->frames;
    293             dprintf("EL#%d: pts=%d  1st_sample=%d  frames=%d (%5.3fs)  pts_offs=%d\n",i,
    294                 el->pos,el->start_sample, el->frames,
    295                 (float)(el->dur)/(float)timescale, el->pts_offset);
    296         }
    297     }
    298 
    299 }
    300 
    301 #define MOV_MAX_TRACKS 256
    302 
    303 typedef struct {
    304     off_t moov_start;
    305     off_t moov_end;
    306     off_t mdat_start;
    307     off_t mdat_end;
    308     int track_db;
    309     mov_track_t* tracks[MOV_MAX_TRACKS];
    310     int timescale; // movie timescale
    311     int duration;  // movie duration (in movie timescale units)
    312 } mov_priv_t;
    313 
    314 #define MOV_FOURCC(a,b,c,d) ((a<<24)|(b<<16)|(c<<8)|(d))
    315 
    316 static int mov_check_file(demuxer_t* demuxer){
    317     int flags=0;
    318     int no=0;
    319     mov_priv_t* priv=malloc(sizeof(mov_priv_t));
    320 
    321     dprintf("Checking for MOV\n");
    322 
    323     memset(priv,0,sizeof(mov_priv_t));
    324 
    325     while(1){
    326         int i;
    327         int skipped=8;
    328         off_t len=stream_read_dword(demuxer->stream);
    329         unsigned int id=stream_read_dword(demuxer->stream);
    330         if(stream_eof(demuxer->stream)) break; // EOF
    331         if (len == 1) /* real size is 64bits - cjb */
    332         {
    333 #ifndef _LARGEFILE_SOURCE
    334             if (stream_read_dword(demuxer->stream) != 0)
    335                 dprintf( "64bit file, but you've compiled MPlayer without LARGEFILE support!\n");
    336             len = stream_read_dword(demuxer->stream);
    337 #else
    338             len = stream_read_qword(demuxer->stream);
     591                 
     592    static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id,
     593                               off_t pos, off_t len, mov_track_t* trak);
     594
     595    static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){
     596        mov_priv_t* priv=demuxer->priv;
     597        //    printf("lschunks (level=%d,endpos=%x)\n", level, endpos);
     598        while(1){
     599            off_t pos;
     600            off_t len;
     601            unsigned int id;
     602            //
     603            pos=stream_tell(demuxer->stream);
     604            dprintf("MOV: stream_tell==%lli\n",pos);
     605            if(pos>=endpos) return; // END
     606            len=stream_read_dword(demuxer->stream);
     607            //  printf("len==%d\n",len);
     608            if(len<8) return; // error
     609            len-=8;
     610            id=stream_read_dword(demuxer->stream);
     611            //
     612            dprintf("lschunks %.4s  %d\n",(char *)&id,(int)len);
     613            //
     614            if(trak){
     615                if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0)
     616                    return;
     617            } else { /* not in track */
     618                switch(id) {
     619                case MOV_FOURCC('m','v','h','d'): {
     620                    int version = stream_read_char(demuxer->stream);
     621                    stream_skip(demuxer->stream, (version == 1) ? 19 : 11);
     622                    priv->timescale=stream_read_dword(demuxer->stream);
     623                    if (version == 1)
     624                        priv->duration=stream_read_qword(demuxer->stream);
     625                    else
     626                        priv->duration=stream_read_dword(demuxer->stream);
     627                    dprintf("MOV: %*sMovie header (%d bytes): tscale=%d  dur=%d\n",level,"",(int)len,
     628                            (int)priv->timescale,(int)priv->duration);
     629                    break;
     630                }
     631                case MOV_FOURCC('t','r','a','k'): {
     632                    //      if(trak) printf("MOV: Warning! trak in trak?\n");
     633                    if(priv->track_db>=MOV_MAX_TRACKS){
     634                        dprintf("MOV: too may tracks\n");
     635                        return;
     636                    }
     637                    if(!priv->track_db) dprintf( "--------------\n");
     638                    trak=malloc(sizeof(mov_track_t));
     639                    memset(trak,0,sizeof(mov_track_t));
     640                    dprintf("MOV: Track #%d:\n",priv->track_db);
     641                    trak->id=priv->track_db;
     642                    priv->tracks[priv->track_db]=trak;
     643                    lschunks(demuxer,level+1,pos+len,trak);
     644                    mov_build_index(trak,priv->timescale);
     645                    switch(trak->type){
     646                    case MOV_TRAK_AUDIO: {
     647#if 0
     648                        struct {
     649                            int16_t version;            // 0 or 1 (version 1 is qt3.0+)
     650                            int16_t revision;           // 0
     651                            int32_t vendor_id;          // 0
     652                            int16_t channels;           // 1 or 2  (Mono/Stereo)
     653                            int16_t samplesize;         // 8 or 16 (8Bit/16Bit)
     654                            int16_t compression_id;     // if version 0 then 0
     655                            // if version 1 and vbr then -2 else 0
     656                            int16_t packet_size;                // 0
     657                            uint16_t sample_rate;       // samplerate (Hz)
     658                            // qt3.0+ (version == 1)
     659                            uint32_t samples_per_packet;        // 0 or num uncompressed samples in a packet
     660                            // if 0 below three values are also 0
     661                            uint32_t bytes_per_packet;  // 0 or num compressed bytes for one channel
     662                            uint32_t bytes_per_frame;   // 0 or num compressed bytes for all channels
     663                            // (channels * bytes_per_packet)
     664                            uint32_t bytes_per_sample;  // 0 or size of uncompressed sample
     665                            // if samples_per_packet and bytes_per_packet are constant (CBR)
     666                            // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR)
     667                            // ---
     668                            // optional additional atom-based fields
     669                            // ([int32_t size,int32_t type,some data ],repeat)
     670                        } my_stdata;
    339671#endif
    340             skipped += 8;
    341         }
    342 #if 0
    343         else if (len == 0) /* deleted chunk */
    344         {
    345             /* XXX: CJB! is this right? - alex */
    346             goto skip_chunk;
    347         }
    348 #endif
    349         else if(len<8) break; // invalid chunk
    350 
    351         switch(id){
    352         case MOV_FOURCC('f','t','y','p'): {
    353           unsigned int tmp;
    354           // File Type Box (ftyp):
    355           // char[4]  major_brand          (eg. 'isom')
    356           // int      minor_version        (eg. 0x00000000)
    357           // char[4]  compatible_brands[]  (eg. 'mp41')
    358           // compatible_brands list spans to the end of box
    359 #if 1
    360           tmp = stream_read_dword(demuxer->stream);
    361           switch(tmp) {
    362             case MOV_FOURCC('i','s','o','m'):
    363               dprintf("ISO: File Type Major Brand: ISO Base Media\n");
    364               break;
    365             case MOV_FOURCC('m','p','4','1'):
    366               dprintf("ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v1\n");
    367               break;
    368             case MOV_FOURCC('m','p','4','2'):
    369               dprintf("ISO: File Type Major Brand: ISO/IEC 14496-1 (MPEG-4 system) v2\n");
    370               break;
    371             case MOV_FOURCC('M','4','A',' '):
    372               dprintf("ISO: File Type Major Brand: Apple iTunes AAC-LC Audio\n");
    373               break;
    374             case MOV_FOURCC('M','4','P',' '):
    375               dprintf("ISO: File Type Major Brand: Apple iTunes AAC-LC Protected Audio\n");
    376               break;
    377             case MOV_FOURCC('q','t',' ',' '):
    378               dprintf("ISO: File Type Major Brand: Original QuickTime\n");
    379               break;
    380             case MOV_FOURCC('3','g','p','1'):
    381               dprintf("ISO: File Type Major Brand: 3GPP Profile 1\n");
    382               break;
    383             case MOV_FOURCC('3','g','p','2'):
    384             case MOV_FOURCC('3','g','2','a'):
    385               dprintf("ISO: File Type Major Brand: 3GPP Profile 2\n");
    386               break;
    387             case MOV_FOURCC('3','g','p','3'):
    388               dprintf("ISO: File Type Major Brand: 3GPP Profile 3\n");
    389               break;
    390             case MOV_FOURCC('3','g','p','4'):
    391               dprintf("ISO: File Type Major Brand: 3GPP Profile 4\n");
    392               break;
    393             case MOV_FOURCC('3','g','p','5'):
    394               dprintf("ISO: File Type Major Brand: 3GPP Profile 5\n");
    395               break;
    396             case MOV_FOURCC('m','m','p','4'):
    397               dprintf("ISO: File Type Major Brand: Mobile ISO/IEC 14496-1 (MPEG-4 system)\n");
    398               break;
    399             default:
    400               tmp = be2me_32(tmp);
    401               dprintf("ISO: Unknown File Type Major Brand: %.4s\n",(char *)&tmp);
    402           }
    403           dprintf("ISO: File Type Minor Version: %d\n",
    404               stream_read_dword(demuxer->stream));
    405           skipped += 8;
    406           // List all compatible brands
    407           for(i = 0; i < ((len-16)/4); i++) {
    408             tmp = be2me_32(stream_read_dword(demuxer->stream));
    409             dprintf("ISO: File Type Compatible Brand #%d: %.4s\n",i,(char *)&tmp);
    410             skipped += 4;
    411           }
    412 #endif
    413           } break;
    414         case MOV_FOURCC('m','o','o','v'):
    415 //      case MOV_FOURCC('c','m','o','v'):
    416           dprintf("MOV: Movie header found!\n");
    417           priv->moov_start=(off_t)stream_tell(demuxer->stream);
    418           priv->moov_end=(off_t)priv->moov_start+len-skipped;
    419           dprintf("MOV: Movie header: start: %"PRIx64" end: %"PRIx64"\n",
    420             (int64_t)priv->moov_start, (int64_t)priv->moov_end);
    421           skipped+=8;
    422           i = stream_read_dword(demuxer->stream)-8;
    423           if(stream_read_dword(demuxer->stream)==MOV_FOURCC('r','m','r','a')){
    424               int ref=0;
    425               skipped+=i;
    426               dprintf("MOV: Reference Media file!!!\n");
    427               //set demuxer type to playlist ...
    428               demuxer->type=DEMUXER_TYPE_PLAYLIST;
    429               while(i>0){
    430                   int len=stream_read_dword(demuxer->stream)-8;
    431                   int fcc=stream_read_dword(demuxer->stream);
    432                   if(len<0) break; // EOF!?
    433                   i-=8;
    434 //                printf("i=%d  len=%d\n",i,len);
    435                   switch(fcc){
    436                   case MOV_FOURCC('r','m','d','a'):
    437                       continue;
    438                   case MOV_FOURCC('r','d','r','f'): {
    439                       int tmp=stream_read_dword(demuxer->stream);
    440                       int type=stream_read_dword_le(demuxer->stream);
    441                       int slen=stream_read_dword(demuxer->stream);
    442                       //char* s=malloc(slen+1);
    443                       //stream_read(demuxer->stream,s,slen);
    444 
    445                       //FIXME: also store type & data_rate ?
    446                       ds_read_packet(demuxer->video,
    447                         demuxer->stream,
    448                         slen,
    449                         0,
    450                         stream_tell(demuxer->stream),
    451                         0 // no flags
    452                       );
    453                       flags|=4;
    454                       dprintf("Added reference to playlist\n");
    455                       //s[slen]=0;
    456                       //dprintf("REF: [%.4s] %s\n",&type,s);
    457                       len-=12+slen;i-=12+slen; break;
    458                     }
    459                   case MOV_FOURCC('r','m','d','r'): {
    460                       int flags=stream_read_dword(demuxer->stream);
    461                       int rate=stream_read_dword(demuxer->stream);
    462                       dprintf("  min. data rate: %d bits/sec\n",rate);
    463                       len-=8; i-=8; break;
    464                     }
    465                   case MOV_FOURCC('r','m','q','u'): {
    466                       int q=stream_read_dword(demuxer->stream);
    467                       dprintf("  quality index: %d\n",q);
    468                       len-=4; i-=4; break;
    469                     }
    470                   }
    471                   i-=len;stream_skip(demuxer->stream,len);
    472               }
    473           }
    474           flags|=1;
    475           break;
    476         case MOV_FOURCC('w','i','d','e'):
    477           dprintf("MOV: 'WIDE' chunk found!\n");
    478           if(flags&2) break;
    479         case MOV_FOURCC('m','d','a','t'):
    480           dprintf("MOV: Movie DATA found!\n");
    481           priv->mdat_start=stream_tell(demuxer->stream);
    482           priv->mdat_end=priv->mdat_start+len-skipped;
    483           dprintf("MOV: Movie data: start: %"PRIx64" end: %"PRIx64"\n",
    484             (int64_t)priv->mdat_start, (int64_t)priv->mdat_end);
    485           flags|=2;
    486           if(flags==3){
    487             // if we're over the headers, then we can stop parsing here!
    488             demuxer->priv=priv;
    489             return DEMUXER_TYPE_MOV;
    490           }
    491           break;
    492         case MOV_FOURCC('f','r','e','e'):
    493         case MOV_FOURCC('s','k','i','p'):
    494         case MOV_FOURCC('j','u','n','k'):
    495           dprintf("MOV: free space (len: %"PRId64")\n", (int64_t)len);
    496           /* unused, if you edit a mov, you can use space provided by free atoms (redefining it) */
    497           break;
    498         case MOV_FOURCC('p','n','o','t'):
    499         case MOV_FOURCC('P','I','C','T'):
    500           /* dunno what, but we shoudl ignore it */
    501           break;
    502         default:
    503           if(no==0){ free(priv); return 0;} // first chunk is bad!
    504           id = be2me_32(id);
    505           dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
    506         }
    507 skip_chunk:
    508         if(!stream_skip(demuxer->stream,len-skipped)) break;
    509         ++no;
    510     }
    511 
    512     if(flags==3){
    513         demuxer->priv=priv;
    514         return DEMUXER_TYPE_MOV;
    515     }
    516     free(priv);
    517 
    518     if ((flags==5) || (flags==7)) // reference & header sent
    519         return DEMUXER_TYPE_PLAYLIST;
    520 
    521     if(flags==1)
    522         dprintf("MOV: missing data (mdat) chunk! Maybe broken file...\n");
    523     else if(flags==2)
    524         dprintf("MOV: missing header (moov/cmov) chunk! Maybe broken file...\n");
    525 
    526     return 0;
    527 }
    528 
    529 static void demux_close_mov(demuxer_t *demuxer) {
    530   mov_priv_t* priv = demuxer->priv;
    531   int i;
    532   if (!priv)
    533     return;
    534   for (i = 0; i < MOV_MAX_TRACKS; i++) {
    535     mov_track_t *track = priv->tracks[i];
    536     if (track) {
    537       free(track->tkdata);
    538       free(track->stdata);
    539       free(track->stream_header);
    540       free(track->samples);
    541       free(track->chunks);
    542       free(track->chunkmap);
    543       free(track->durmap);
    544       free(track->keyframes);
    545       free(track->editlist);
    546       free(track->desc);
    547       free(track);
    548     }
    549   }
    550   free(priv);
    551 }
    552 
    553 unsigned int store_ughvlc(unsigned char *s, unsigned int v){
    554     unsigned int n = 0;
    555 
    556     while(v >= 0xff) {
    557         *s++ = 0xff;
    558         v -= 0xff;
    559         n++;
    560     }
    561     *s = v;
    562     n++;
    563 
    564     return n;
    565 }
    566 
    567 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id,
    568                            off_t pos, off_t len, mov_track_t* trak);
    569 
    570 static void lschunks(demuxer_t* demuxer,int level,off_t endpos,mov_track_t* trak){
    571     mov_priv_t* priv=demuxer->priv;
    572     //    printf("lschunks (level=%d,endpos=%x)\n", level, endpos);
    573     while(1){
    574         off_t pos;
    575         off_t len;
    576         unsigned int id;
    577         //
    578         pos=stream_tell(demuxer->stream);
    579         dprintf("MOV: stream_tell==%lli\n",pos);
    580         if(pos>=endpos) return; // END
    581         len=stream_read_dword(demuxer->stream);
    582         //      printf("len==%d\n",len);
    583         if(len<8) return; // error
    584         len-=8;
    585         id=stream_read_dword(demuxer->stream);
    586         //
    587         dprintf("lschunks %.4s  %d\n",(char *)&id,(int)len);
    588         //
    589         if(trak){
    590             if (lschunks_intrak(demuxer, level, id, pos, len, trak) < 0)
    591                 return;
    592         } else { /* not in track */
    593             switch(id) {
    594             case MOV_FOURCC('m','v','h','d'): {
    595                 int version = stream_read_char(demuxer->stream);
    596                 stream_skip(demuxer->stream, (version == 1) ? 19 : 11);
    597                 priv->timescale=stream_read_dword(demuxer->stream);
    598                 if (version == 1)
    599                     priv->duration=stream_read_qword(demuxer->stream);
    600                 else
    601                     priv->duration=stream_read_dword(demuxer->stream);
    602                 dprintf("MOV: %*sMovie header (%d bytes): tscale=%d  dur=%d\n",level,"",(int)len,
    603                         (int)priv->timescale,(int)priv->duration);
    604                 break;
    605             }
    606             case MOV_FOURCC('t','r','a','k'): {
    607                 //          if(trak) printf("MOV: Warning! trak in trak?\n");
    608                 if(priv->track_db>=MOV_MAX_TRACKS){
    609                     dprintf("MOV: too may tracks\n");
    610                     return;
    611                 }
    612                 if(!priv->track_db) dprintf( "--------------\n");
    613                 trak=malloc(sizeof(mov_track_t));
    614                 memset(trak,0,sizeof(mov_track_t));
    615                 dprintf("MOV: Track #%d:\n",priv->track_db);
    616                 trak->id=priv->track_db;
    617                 priv->tracks[priv->track_db]=trak;
    618                 lschunks(demuxer,level+1,pos+len,trak);
    619                 mov_build_index(trak,priv->timescale);
    620                 switch(trak->type){
    621                 case MOV_TRAK_AUDIO: {
    622 #if 0
    623                     struct {
    624                         int16_t version;                // 0 or 1 (version 1 is qt3.0+)
    625                         int16_t revision;               // 0
    626                         int32_t vendor_id;              // 0
    627                         int16_t channels;               // 1 or 2  (Mono/Stereo)
    628                         int16_t samplesize;             // 8 or 16 (8Bit/16Bit)
    629                         int16_t compression_id; // if version 0 then 0
    630                         // if version 1 and vbr then -2 else 0
    631                         int16_t packet_size;            // 0
    632                         uint16_t sample_rate;   // samplerate (Hz)
    633                         // qt3.0+ (version == 1)
    634                         uint32_t samples_per_packet;    // 0 or num uncompressed samples in a packet
    635                         // if 0 below three values are also 0
    636                         uint32_t bytes_per_packet;      // 0 or num compressed bytes for one channel
    637                         uint32_t bytes_per_frame;       // 0 or num compressed bytes for all channels
    638                         // (channels * bytes_per_packet)
    639                         uint32_t bytes_per_sample;      // 0 or size of uncompressed sample
    640                         // if samples_per_packet and bytes_per_packet are constant (CBR)
    641                         // then bytes_per_frame and bytes_per_sample must be 0 (else is VBR)
    642                         // ---
    643                         // optional additional atom-based fields
    644                         // ([int32_t size,int32_t type,some data ],repeat)
    645                     } my_stdata;
    646 #endif
    647                     int version, adjust;
    648                     int is_vorbis = 0;
    649                     sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db);
    650                     sh->format=trak->fourcc;
    651 
    652                     // crude audio delay from editlist0 hack ::atm
    653                     if(trak->editlist_size>=1) {
    654                         if(trak->editlist[0].pos == -1) {
    655                             sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale;
    656                             dprintf("MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay);
     672                        int version, adjust;
     673                        int is_vorbis = 0;
     674                        sh_audio_t* sh=new_sh_audio(demuxer,priv->track_db);
     675                        sh->format=trak->fourcc;
     676
     677                        // crude audio delay from editlist0 hack ::atm
     678                        if(trak->editlist_size>=1) {
     679                            if(trak->editlist[0].pos == -1) {
     680                                sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale;
     681                                dprintf("MOV: Initial Audio-Delay: %.3f sec\n", sh->stream_delay);
     682                            }
    657683                        }
    658                     }
    659 
    660                     switch( sh->format ) {
    661                     case 0x726D6173: /* samr */
    662                         /* amr narrowband */
    663                         trak->samplebytes=sh->samplesize=1;
    664                         trak->nchannels=sh->channels=1;
    665                         sh->samplerate=8000;
    666                         break;
    667 
    668                     case 0x62776173: /* sawb */
    669                         /* amr wideband */
    670                         trak->samplebytes=sh->samplesize=1;
    671                         trak->nchannels=sh->channels=1;
    672                         sh->samplerate=16000;
    673                         break;
    674 
    675                     default:
    676 
    677                         // assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit
    678                         // XXX: 32bit fixed point numbers (intfp) are only 2 Byte!
    679                         // short values are usually one byte leftpadded by zero
    680                         //   int values are usually two byte leftpadded by zero
    681                         //  stdata[]:
    682                         //      8   short       version
    683                         //      10  short       revision
    684                         //      12  int         vendor_id
    685                         //      16  short       channels
    686                         //      18  short       samplesize
    687                         //      20  short       compression_id
    688                         //      22  short       packet_size (==0)
    689                         //      24  intfp       sample_rate
    690                         //     (26  short)      unknown (==0)
    691                         //    ---- qt3.0+ (version>=1)
    692                         //      28  int         samples_per_packet
    693                         //      32  int         bytes_per_packet
    694                         //      36  int         bytes_per_frame
    695                         //      40  int         bytes_per_sample
    696                         // there may be additional atoms following at 28 (version 0)
    697                         // or 44 (version 1), eg. esds atom of .MP4 files
    698                         // esds atom:
    699                         //      28  int         atom size (bytes of int size, int type and data)
    700                         //      32  char[4]     atom type (fourc charater code -> esds)
    701                         //      36  char[]      atom data (len=size-8)
    702 
    703                         // TODO: fix parsing for files using version 2.
    704                         version=char2short(trak->stdata,8);
    705                         if (version > 1)
    706                             dprintf( "MOV: version %d sound atom may not parse correctly!\n", version);
    707                         trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8;
    708 
    709                         /* I can't find documentation, but so far this is the case. -Corey */
    710                         switch (char2short(trak->stdata,16)) {
    711                         case 1:
    712                             trak->nchannels = 1; break;
    713                         case 2:
    714                             trak->nchannels = 2; break;
    715                         case 3:
    716                             trak->nchannels = 6; break;
     684
     685                        switch( sh->format ) {
     686                        case 0x726D6173: /* samr */
     687                            /* amr narrowband */
     688                            trak->samplebytes=sh->samplesize=1;
     689                            trak->nchannels=sh->channels=1;
     690                            sh->samplerate=8000;
     691                            break;
     692
     693                        case 0x62776173: /* sawb */
     694                            /* amr wideband */
     695                            trak->samplebytes=sh->samplesize=1;
     696                            trak->nchannels=sh->channels=1;
     697                            sh->samplerate=16000;
     698                            break;
     699
    717700                        default:
    718                             dprintf(
    719                                     "MOV: unable to determine audio channels, assuming 2 (got %d)\n",
    720                                     char2short(trak->stdata,16));
    721                             trak->nchannels = 2;
    722                         }
    723                         sh->channels = trak->nchannels;
    724 
    725                         /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n",
    726                          trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur,
    727                          trak->durmap[0].num, trak->timescale/trak->durmap[0].dur,
    728                          char2short(trak->stdata,24)/trak->durmap[0].dur);*/
    729                         sh->samplerate=char2short(trak->stdata,24);
    730                         if((sh->samplerate < 7000) && trak->durmap) {
    731                             switch(char2short(trak->stdata,24)/trak->durmap[0].dur) {
    732                                 // TODO: add more cases.
    733                             case 31:
    734                                 sh->samplerate = 32000; break;
    735                             case 43:
    736                                 sh->samplerate = 44100; break;
    737                             case 47:
    738                                 sh->samplerate = 48000; break;
     701
     702                            // assumptions for below table: short is 16bit, int is 32bit, intfp is 16bit
     703                            // XXX: 32bit fixed point numbers (intfp) are only 2 Byte!
     704                            // short values are usually one byte leftpadded by zero
     705                            //   int values are usually two byte leftpadded by zero
     706                            //  stdata[]:
     707                            //  8   short       version
     708                            //  10  short       revision
     709                            //  12  int         vendor_id
     710                            //  16  short       channels
     711                            //  18  short       samplesize
     712                            //  20  short       compression_id
     713                            //  22  short       packet_size (==0)
     714                            //  24  intfp       sample_rate
     715                            //     (26  short)  unknown (==0)
     716                            //    ---- qt3.0+ (version>=1)
     717                            //  28  int         samples_per_packet
     718                            //  32  int         bytes_per_packet
     719                            //  36  int         bytes_per_frame
     720                            //  40  int         bytes_per_sample
     721                            // there may be additional atoms following at 28 (version 0)
     722                            // or 44 (version 1), eg. esds atom of .MP4 files
     723                            // esds atom:
     724                            //      28  int             atom size (bytes of int size, int type and data)
     725                            //      32  char[4] atom type (fourc charater code -> esds)
     726                            //      36  char[]          atom data (len=size-8)
     727
     728                            // TODO: fix parsing for files using version 2.
     729                            version=char2short(trak->stdata,8);
     730                            if (version > 1)
     731                                dprintf( "MOV: version %d sound atom may not parse correctly!\n", version);
     732                            trak->samplebytes=sh->samplesize=char2short(trak->stdata,18)/8;
     733
     734                            /* I can't find documentation, but so far this is the case. -Corey */
     735                            switch (char2short(trak->stdata,16)) {
     736                            case 1:
     737                                trak->nchannels = 1; break;
     738                            case 2:
     739                                trak->nchannels = 2; break;
     740                            case 3:
     741                                trak->nchannels = 6; break;
    739742                            default:
    740743                                dprintf(
    741                                         "MOV: unable to determine audio samplerate, "
    742                                         "assuming 44.1kHz (got %d)\n",
    743                                         char2short(trak->stdata,24)/trak->durmap[0].dur);
    744                                 sh->samplerate = 44100;
     744                                        "MOV: unable to determine audio channels, assuming 2 (got %d)\n",
     745                                        char2short(trak->stdata,16));
     746                                trak->nchannels = 2;
     747                            }
     748                            sh->channels = trak->nchannels;
     749
     750                            /*printf("MOV: timescale: %d samplerate: %d durmap: %d (%d) -> %d (%d)\n",
     751                             trak->timescale, char2short(trak->stdata,24), trak->durmap[0].dur,
     752                             trak->durmap[0].num, trak->timescale/trak->durmap[0].dur,
     753                             char2short(trak->stdata,24)/trak->durmap[0].dur);*/
     754                            sh->samplerate=char2short(trak->stdata,24);
     755                            if((sh->samplerate < 7000) && trak->durmap) {
     756                                switch(char2short(trak->stdata,24)/trak->durmap[0].dur) {
     757                                    // TODO: add more cases.
     758                                case 31:
     759                                    sh->samplerate = 32000; break;
     760                                case 43:
     761                                    sh->samplerate = 44100; break;
     762                                case 47:
     763                                    sh->samplerate = 48000; break;
     764                                default:
     765                                    dprintf(
     766                                            "MOV: unable to determine audio samplerate, "
     767                                            "assuming 44.1kHz (got %d)\n",
     768                                            char2short(trak->stdata,24)/trak->durmap[0].dur);
     769                                    sh->samplerate = 44100;
     770                                }
    745771                            }
    746772                        }
    747                     }
    748                     dprintf( "Audio bits: %d  chans: %d  rate: %d\n",
    749                             sh->samplesize*8,sh->channels,sh->samplerate);
    750 
    751                     if(trak->stdata_len >= 44 && trak->stdata[9]>=1){
    752                         dprintf("Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d  \n",
    753                                 char2int(trak->stdata,28),
    754                                 char2int(trak->stdata,32),
    755                                 char2int(trak->stdata,36),
    756                                 char2int(trak->stdata,40));
    757                         if(trak->stdata_len>=44+8){
    758                             int len=char2int(trak->stdata,44);
    759                             int fcc=char2int(trak->stdata,48);
    760                             // we have extra audio headers!!!
    761                             dprintf("Audio extra header: len=%d  fcc=0x%X\n",len,fcc);
    762                             if((len >= 4) &&
    763                                (char2int(trak->stdata,52) >= 12) &&
    764                                (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a'))) {
    765                                 switch(char2int(trak->stdata,52+8)) {
    766                                 case MOV_FOURCC('a','l','a','c'):
    767                                     if (len >= 36 + char2int(trak->stdata,52)) {
    768                                         sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52));
    769                                         dprintf( "MOV: Found alac atom (%d)!\n", sh->codecdata_len);
    770                                         sh->codecdata = (unsigned char *)malloc(sh->codecdata_len);
    771                                         memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len);
     773                        dprintf( "Audio bits: %d  chans: %d  rate: %d\n",
     774                                sh->samplesize*8,sh->channels,sh->samplerate);
     775
     776                        if(trak->stdata_len >= 44 && trak->stdata[9]>=1){
     777                            dprintf("Audio header: samp/pack=%d bytes/pack=%d bytes/frame=%d bytes/samp=%d  \n",
     778                                    char2int(trak->stdata,28),
     779                                    char2int(trak->stdata,32),
     780                                    char2int(trak->stdata,36),
     781                                    char2int(trak->stdata,40));
     782                            if(trak->stdata_len>=44+8){
     783                                int len=char2int(trak->stdata,44);
     784                                int fcc=char2int(trak->stdata,48);
     785                                // we have extra audio headers!!!
     786                                dprintf("Audio extra header: len=%d  fcc=0x%X\n",len,fcc);
     787                                if((len >= 4) &&
     788                                   (char2int(trak->stdata,52) >= 12) &&
     789                                   (char2int(trak->stdata,52+4) == MOV_FOURCC('f','r','m','a'))) {
     790                                    switch(char2int(trak->stdata,52+8)) {
     791                                    case MOV_FOURCC('a','l','a','c'):
     792                                        if (len >= 36 + char2int(trak->stdata,52)) {
     793                                            sh->codecdata_len = char2int(trak->stdata,52+char2int(trak->stdata,52));
     794                                            dprintf( "MOV: Found alac atom (%d)!\n", sh->codecdata_len);
     795                                            sh->codecdata = (unsigned char *)malloc(sh->codecdata_len);
     796                                            memcpy(sh->codecdata, &trak->stdata[52+char2int(trak->stdata,52)], sh->codecdata_len);
     797                                        }
     798                                        break;
     799                                    case MOV_FOURCC('i','n','2','4'):
     800                                    case MOV_FOURCC('i','n','3','2'):
     801                                    case MOV_FOURCC('f','l','3','2'):
     802                                    case MOV_FOURCC('f','l','6','4'):
     803                                        if ((len >= 22) &&
     804                                            (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) &&
     805                                            (char2short(trak->stdata,52+20))) {
     806                                            sh->format=char2int(trak->stdata,52+8);
     807                                            dprintf( "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format);
     808                                        }
     809                                        break;
     810                                    default:
     811                                        if (len > 8 && len + 44 <= trak->stdata_len) {
     812                                            sh->codecdata_len = len-8;
     813                                            sh->codecdata = trak->stdata+44+8;
     814                                        }
    772815                                    }
    773                                     break;
    774                                 case MOV_FOURCC('i','n','2','4'):
    775                                 case MOV_FOURCC('i','n','3','2'):
    776                                 case MOV_FOURCC('f','l','3','2'):
    777                                 case MOV_FOURCC('f','l','6','4'):
    778                                     if ((len >= 22) &&
    779                                         (char2int(trak->stdata,52+16)==MOV_FOURCC('e','n','d','a')) &&
    780                                         (char2short(trak->stdata,52+20))) {
    781                                         sh->format=char2int(trak->stdata,52+8);
    782                                         dprintf( "MOV: Found little endian PCM data, reversed fourcc:%04x\n", sh->format);
    783                                     }
    784                                     break;
    785                                 default:
     816                                } else {
    786817                                    if (len > 8 && len + 44 <= trak->stdata_len) {
    787818                                        sh->codecdata_len = len-8;
     
    789820                                    }
    790821                                }
    791                             } else {
    792                                 if (len > 8 && len + 44 <= trak->stdata_len) {
    793                                     sh->codecdata_len = len-8;
    794                                     sh->codecdata = trak->stdata+44+8;
     822                            }
     823                        }
     824
     825                        switch (version) {
     826                        case 0:
     827                            adjust =  0; break;
     828                        case 1:
     829                            adjust = 48; break;
     830                        case 2:
     831                            adjust = 68; break;
     832                        default:
     833                            dprintf( "MOV: unknown sound atom version (%d); may not work!\n", version);
     834                            adjust = 68;
     835                        }
     836                        if (trak->stdata_len >= 36 + adjust) {
     837                            int atom_len = char2int(trak->stdata,28+adjust);
     838                            switch(char2int(trak->stdata,32+adjust)) { // atom type
     839                            case MOV_FOURCC('e','s','d','s'): {
     840                                dprintf( "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len);
     841                                if(atom_len > 8) {
     842                                    esds_t esds;
     843                                    if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) {
     844                                        /* 0xdd is a "user private" id, not an official allocated id (see http://www.mp4ra.org/object.html),
     845                                         so perform some extra checks to be sure that this is really vorbis audio */
     846                                        if(esds.objectTypeId==0xdd && esds.streamType==0x15 && sh->format==0x6134706D && esds.decoderConfigLen > 8)
     847                                        {
     848                                            //vorbis audio
     849                                            unsigned char *buf[3];
     850                                            unsigned short sizes[3];
     851                                            int offset, len, k;
     852                                            unsigned char *ptr = esds.decoderConfig;
     853
     854                                            if(ptr[0] != 0 || ptr[1] != 30) goto quit_vorbis_block; //wrong extradata layout
     855
     856                                            offset = len = 0;
     857                                            for(k = 0; k < 3; k++)
     858                                            {
     859                                                sizes[k] = (ptr[offset]<<8) | ptr[offset+1];
     860                                                len += sizes[k];
     861                                                offset += 2;
     862                                                if(offset + sizes[k] > esds.decoderConfigLen)
     863                                                {
     864                                                    dprintf("MOV: ERROR!, not enough vorbis extradata to read: offset = %d, k=%d, size=%d, len: %d\n", offset, k, sizes[k], esds.decoderConfigLen);
     865                                                    goto quit_vorbis_block;
     866                                                }
     867                                                buf[k] = malloc(sizes[k]);
     868                                                if(!buf[k]) goto quit_vorbis_block;
     869                                                memcpy(buf[k], &ptr[offset], sizes[k]);
     870                                                offset += sizes[k];
     871                                            }
     872
     873                                            sh->codecdata_len = len + len/255 + 64;
     874                                            sh->codecdata = malloc(sh->codecdata_len);
     875                                            ptr = sh->codecdata;
     876
     877                                            ptr[0] = 2;
     878                                            offset = 1;
     879                                            offset += store_ughvlc(&ptr[offset], sizes[0]);
     880                                            offset += store_ughvlc(&ptr[offset], sizes[1]);
     881                                            for(k = 0; k < 3; k++)
     882                                            {
     883                                                memcpy(&ptr[offset], buf[k], sizes[k]);
     884                                                offset += sizes[k];
     885                                            }
     886
     887                                            sh->codecdata_len = offset;
     888                                            sh->codecdata = realloc(sh->codecdata, offset);
     889                                            dprintf("demux_mov, vorbis extradata size: %d\n", offset);
     890                                            is_vorbis = 1;
     891                                        quit_vorbis_block:
     892                                            sh->format = mmioFOURCC('v', 'r', 'b', 's');
     893                                        }
     894                                        sh->i_bps = esds.avgBitrate/8;
     895
     896                                        //                          printf("######## audio format = %d ########\n",esds.objectTypeId);
     897                                        if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3)
     898                                            sh->format=0x55; // .mp3
     899                                        if(esds.objectTypeId==MP4OTI_13kVoice) { // 13K Voice, defined by 3GPP2
     900                                            sh->format=mmioFOURCC('Q', 'c', 'l', 'p');
     901                                            trak->nchannels=sh->channels=1;
     902                                            trak->samplebytes=sh->samplesize=1;
     903                                        }
     904
     905                                        // dump away the codec specific configuration for the AAC decoder
     906                                        if(esds.decoderConfigLen){
     907                                            if( (esds.decoderConfig[0]>>3) == 29 )
     908                                                sh->format = 0x1d61346d; // request multi-channel mp3 decoder
     909                                            if(!is_vorbis)
     910                                            {
     911                                                sh->codecdata_len = esds.decoderConfigLen;
     912                                                sh->codecdata = (unsigned char *)malloc(sh->codecdata_len);
     913                                                memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len);
     914                                            }
     915                                        }
     916                                    }
     917                                    mp4_free_esds(&esds); // freeup esds mem
     918#if 0
     919                                    { FILE* f=fopen("esds.dat","wb");
     920                                        fwrite(&trak->stdata[36],atom_len-8,1,f);
     921                                    fclose(f); }
     922#endif
     923                                }
     924                            } break;
     925                            case MOV_FOURCC('a','l','a','c'): {
     926                                dprintf( "MOV: Found alac atom (%d)!\n", atom_len);
     927                                if(atom_len > 8) {
     928                                    // copy all the atom (not only payload) for lavc alac decoder
     929                                    sh->codecdata_len = atom_len;
     930                                    sh->codecdata = (unsigned char *)malloc(sh->codecdata_len);
     931                                    memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len);
     932                                }
     933                            } break;
     934                            case MOV_FOURCC('d','a','m','r'):
     935                                dprintf( "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len);
     936                                if (atom_len>14) {
     937                                    dprintf( "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]);
     938                                    dprintf( "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]);
     939                                    dprintf( "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]);
     940                                }
     941                                break;
     942                            default:
     943                                dprintf( "MOV: Found unknown audio atom %c%c%c%c (%d)!\n",
     944                                        trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust],
     945                                        atom_len);
     946                            }
     947                        }
     948                        dprintf( "Fourcc: %.4s\n",(char *)&trak->fourcc);
     949#if 0
     950                        { FILE* f=fopen("stdata.dat","wb");
     951                            fwrite(trak->stdata,trak->stdata_len,1,f);
     952                        fclose(f); }
     953                        { FILE* f=fopen("tkdata.dat","wb");
     954                            fwrite(trak->tkdata,trak->tkdata_len,1,f);
     955                        fclose(f); }
     956#endif
     957                        // Emulate WAVEFORMATEX struct:
     958                        sh->wf=malloc(sizeof(WAVEFORMATEX) + (is_vorbis ? sh->codecdata_len : 0));
     959                        memset(sh->wf,0,sizeof(WAVEFORMATEX));
     960                        sh->wf->nChannels=sh->channels;
     961                        sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19];
     962                        // sh->wf->nSamplesPerSec=trak->timescale;
     963                        sh->wf->nSamplesPerSec=sh->samplerate;
     964                        if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){
     965                            //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2
     966                            sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec*
     967                                                     char2int(trak->stdata,32)+char2int(trak->stdata,28)/2)
     968                                /char2int(trak->stdata,28);
     969                            sh->wf->nBlockAlign=char2int(trak->stdata,36);
     970                        } else {
     971                            sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8;
     972                            // workaround for ms11 ima4
     973                            if (sh->format == 0x1100736d && trak->stdata_len >= 36)
     974                                sh->wf->nBlockAlign=char2int(trak->stdata,36);
     975                        }
     976                        if(is_vorbis && sh->codecdata_len)
     977                        {
     978                            memcpy(sh->wf+1, sh->codecdata, sh->codecdata_len);
     979                            sh->wf->cbSize = sh->codecdata_len;
     980                        }
     981                        // Selection:
     982                        //              if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){
     983                        //                  // (auto)selected audio track:
     984                        //                  demuxer->audio->id=priv->track_db;
     985                        //                  demuxer->audio->sh=sh; sh->ds=demuxer->audio;
     986                        //              }
     987                        break;
     988                    }
     989                    case MOV_TRAK_VIDEO: {
     990                        int i, entry;
     991                        int flag, start, count_flag, end, palette_count, gray;
     992                        int hdr_ptr = 76;  // the byte just after depth
     993                        unsigned char *palette_map;
     994                        sh_video_t* sh=new_sh_video(demuxer,priv->track_db);
     995                        int depth;
     996                        sh->format=trak->fourcc;
     997
     998                        // crude video delay from editlist0 hack ::atm
     999                        if(trak->editlist_size>=1) {
     1000                            if(trak->editlist[0].pos == -1) {
     1001                                sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale;
     1002                                dprintf("MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay);
     1003                            }
     1004                        }
     1005
     1006                        if (trak->stdata_len < 78) {
     1007                            dprintf("MOV: Invalid (%d bytes instead of >= 78) video trak desc\n",
     1008                                    trak->stdata_len);
     1009                            break;
     1010                        }
     1011                        depth = trak->stdata[75] | (trak->stdata[74] << 8);
     1012                        //  stdata[]:
     1013                        //      8   short       version
     1014                        //      10  short       revision
     1015                        //      12  int         vendor_id
     1016                        //      16  int         temporal_quality
     1017                        //      20  int         spatial_quality
     1018                        //      24  short       width
     1019                        //      26  short       height
     1020                        //      28  int         h_dpi
     1021                        //      32  int         v_dpi
     1022                        //      36  int         0
     1023                        //      40  short       frames_per_sample
     1024                        //      42  char[4]     compressor_name
     1025                        //      74  short       depth
     1026                        //      76  short       color_table_id
     1027                        // additional atoms may follow,
     1028                        // eg esds atom from .MP4 files
     1029                        //      78  int         atom size
     1030                        //      82  char[4]     atom type
     1031                        //      86  ...         atom data
     1032
     1033                        {       ImageDescription* id=malloc(8+trak->stdata_len);  // safe
     1034                            trak->desc=id;
     1035                        id->idSize=8+trak->stdata_len;
     1036                        //              id->cType=bswap_32(trak->fourcc);
     1037                        id->cType=le2me_32(trak->fourcc);
     1038                        id->version=char2short(trak->stdata,8);
     1039                        id->revisionLevel=char2short(trak->stdata,10);
     1040                        id->vendor=char2int(trak->stdata,12);
     1041                        id->temporalQuality=char2int(trak->stdata,16);
     1042                        id->spatialQuality=char2int(trak->stdata,20);
     1043                        id->width=char2short(trak->stdata,24);
     1044                        id->height=char2short(trak->stdata,26);
     1045                        id->hRes=char2int(trak->stdata,28);
     1046                        id->vRes=char2int(trak->stdata,32);
     1047                        id->dataSize=char2int(trak->stdata,36);
     1048                        id->frameCount=char2short(trak->stdata,40);
     1049                        memcpy(&id->name,trak->stdata+42,32);
     1050                        id->depth=char2short(trak->stdata,74);
     1051                        id->clutID=char2short(trak->stdata,76);
     1052                        if(trak->stdata_len>78) memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78);
     1053                        sh->ImageDesc=id;
     1054#if 0
     1055                        {   FILE *f=fopen("ImageDescription","wb");
     1056                            fwrite(id,id->idSize,1,f);
     1057                        fclose(f);
     1058                        }
     1059#endif
     1060                        }
     1061
     1062                        if(trak->stdata_len >= 86) { // extra atoms found
     1063                            int pos=78;
     1064                            int atom_len;
     1065                            while(pos+8<=trak->stdata_len &&
     1066                                  (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){
     1067                                switch(char2int(trak->stdata,pos+4)) { // switch atom type
     1068                                case MOV_FOURCC('g','a','m','a'):
     1069                                    // intfp with gamma value at which movie was captured
     1070                                    // can be used to gamma correct movie display
     1071                                    dprintf( "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n",
     1072                                            atom_len);
     1073                                    break;
     1074                                case MOV_FOURCC('f','i','e','l'):
     1075                                    // 2 char-values (8bit int) that specify field handling
     1076                                    // see the Apple's QuickTime Fileformat PDF for more info
     1077                                    dprintf( "MOV: Found unsupported Field-Handling movie atom (%d)!\n",
     1078                                            atom_len);
     1079                                    break;
     1080                                case MOV_FOURCC('m','j','q','t'):
     1081                                    // Motion-JPEG default quantization table
     1082                                    dprintf( "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n",
     1083                                            atom_len);
     1084                                    break;
     1085                                case MOV_FOURCC('m','j','h','t'):
     1086                                    // Motion-JPEG default huffman table
     1087                                    dprintf( "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n",
     1088                                            atom_len);
     1089                                    break;
     1090                                case MOV_FOURCC('e','s','d','s'):
     1091                                    // MPEG4 Elementary Stream Descriptor header
     1092                                    dprintf( "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len);
     1093                                    // add code here to save esds header of length atom_len-8
     1094                                    // beginning at stdata[86] to some variable to pass it
     1095                                    // on to the decoder ::atmos
     1096                                    if(atom_len > 8) {
     1097                                        esds_t esds;
     1098                                        if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) {
     1099
     1100                                            if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain ||
     1101                                               esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial ||
     1102                                               esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422)
     1103                                                sh->format=mmioFOURCC('m', 'p', 'g', '2');
     1104                                            else if(esds.objectTypeId==MP4OTI_MPEG1Visual)
     1105                                                sh->format=mmioFOURCC('m', 'p', 'g', '1');
     1106
     1107                                            // dump away the codec specific configuration for the AAC decoder
     1108                                            trak->stream_header_len = esds.decoderConfigLen;
     1109                                            trak->stream_header = (unsigned char *)malloc(trak->stream_header_len);
     1110                                            memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len);
     1111                                        }
     1112                                        mp4_free_esds(&esds); // freeup esds mem
     1113                                    }
     1114                                    break;
     1115                                case MOV_FOURCC('a','v','c','C'):
     1116                                    // AVC decoder configuration record
     1117                                    dprintf( "MOV: AVC decoder configuration record atom (%d)!\n", atom_len);
     1118                                    if(atom_len > 8) {
     1119                                        int i, poffs, cnt;
     1120                                        // Parse some parts of avcC, just for fun :)
     1121                                        // real parsing is done by avc1 decoder
     1122                                        dprintf( "MOV: avcC version: %d\n", *(trak->stdata+pos+8));
     1123                                        if (*(trak->stdata+pos+8) != 1)
     1124                                            dprintf( "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9));
     1125                                        dprintf( "MOV: avcC profile: %d\n", *(trak->stdata+pos+9));
     1126                                        dprintf( "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10));
     1127                                        dprintf( "MOV: avcC level: %d\n", *(trak->stdata+pos+11));
     1128                                        dprintf( "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1);
     1129                                        dprintf( "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f));
     1130                                        poffs = pos + 14;
     1131                                        for (i = 0; i < cnt; i++) {
     1132                                            dprintf( "MOV: avcC sps %d have length %d\n", i, BE_16(trak->stdata+poffs));
     1133                                            poffs += BE_16(trak->stdata+poffs) + 2;
     1134                                        }
     1135                                        dprintf( "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs));
     1136                                        poffs++;
     1137                                        for (i = 0; i < cnt; i++) {
     1138                                            dprintf( "MOV: avcC pps %d have length %d\n", i, BE_16(trak->stdata+poffs));
     1139                                            poffs += BE_16(trak->stdata+poffs) + 2;
     1140                                        }
     1141                                        // Copy avcC for the AVC decoder
     1142                                        // This data will be put in extradata below, where BITMAPINFOHEADER is created
     1143                                        trak->stream_header_len = atom_len-8;
     1144                                        trak->stream_header = (unsigned char *)malloc(trak->stream_header_len);
     1145                                        memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len);
     1146                                    }
     1147                                    break;
     1148                                case MOV_FOURCC('d','2','6','3'):
     1149                                    dprintf( "MOV: Found H.263 decoder atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],atom_len);
     1150                                    if (atom_len>10)
     1151                                        dprintf( "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]);
     1152                                    break;
     1153                                case 0:
     1154                                    break;
     1155                                default:
     1156                                    dprintf( "MOV: Found unknown movie atom %c%c%c%c (%d)!\n",
     1157                                            trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],
     1158                                            atom_len);
     1159                                }
     1160                                if(atom_len<8) break;
     1161                                pos+=atom_len;
     1162                                //                 printf("pos=%d max=%d\n",pos,trak->stdata_len);
     1163                            }
     1164                        }
     1165                        sh->fps=trak->timescale/
     1166                            ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1);
     1167                        sh->frametime=1.0f/sh->fps;
     1168
     1169                        sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8);
     1170                        sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8);
     1171                        // if image size is zero, fallback to display size
     1172                        if(!sh->disp_w && !sh->disp_h) {
     1173                            sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8);
     1174                            sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8);
     1175                        } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){
     1176                            // codec and display width differ... use display one for aspect
     1177                            sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8);
     1178                            sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8);
     1179                        }
     1180
     1181                        if(depth>32+8) printf("*** depth = 0x%X\n",depth);
     1182
     1183                        // palettized?
     1184                        gray = 0;
     1185                        if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale
     1186                        if ((depth == 2) || (depth == 4) || (depth == 8))
     1187                            palette_count = (1 << depth);
     1188                        else
     1189                            palette_count = 0;
     1190
     1191                        // emulate BITMAPINFOHEADER:
     1192                        if (palette_count)
     1193                        {
     1194                            sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + palette_count * 4);
     1195                            memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + palette_count * 4);
     1196                            sh->bih->biSize=40 + palette_count * 4;
     1197                            // fetch the relevant fields
     1198                            flag = BE_16(&trak->stdata[hdr_ptr]);
     1199                            hdr_ptr += 2;
     1200                            start = BE_32(&trak->stdata[hdr_ptr]);
     1201                            hdr_ptr += 4;
     1202                            count_flag = BE_16(&trak->stdata[hdr_ptr]);
     1203                            hdr_ptr += 2;
     1204                            end = BE_16(&trak->stdata[hdr_ptr]);
     1205                            hdr_ptr += 2;
     1206                            palette_map = (unsigned char *)sh->bih + 40;
     1207                            dprintf( "Allocated %d entries for palette\n",
     1208                                    palette_count);
     1209                            dprintf( "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n",
     1210                                    start, end, count_flag, flag);
     1211
     1212                            /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/
     1213
     1214                            // load default palette
     1215                            if (flag & 0x08)
     1216                            {
     1217                                if (gray)
     1218                                {
     1219                                    dprintf( "Using default QT grayscale palette\n");
     1220                                    if (palette_count == 16)
     1221                                        memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4);
     1222                                    else if (palette_count == 256) {
     1223                                        memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4);
     1224                                        if (trak->fourcc == mmioFOURCC('c','v','i','d')) {
     1225                                            int i;
     1226                                            // Hack for grayscale CVID, negative palette
     1227                                            // If you have samples where this is not required contact me (rxt)
     1228                                            dprintf( "MOV: greyscale cvid with default palette,"
     1229                                                    " enabling negative palette hack.\n");
     1230                                            for (i = 0; i < 256 * 4; i++)
     1231                                                palette_map[i] = palette_map[i] ^ 0xff;
     1232                                        }
     1233                                    }
     1234                                }
     1235                                else
     1236                                {
     1237                                    dprintf( "Using default QT colour palette\n");
     1238                                    if (palette_count == 4)
     1239                                        memcpy(palette_map, qt_default_palette_4, 4 * 4);
     1240                                    else if (palette_count == 16)
     1241                                        memcpy(palette_map, qt_default_palette_16, 16 * 4);
     1242                                    else if (palette_count == 256)
     1243                                        memcpy(palette_map, qt_default_palette_256, 256 * 4);
     1244                                }
     1245                            }
     1246                            // load palette from file
     1247                            else
     1248                            {
     1249                                dprintf( "Loading palette from file\n");
     1250                                for (i = start; i <= end; i++)
     1251                                {
     1252                                    entry = BE_16(&trak->stdata[hdr_ptr]);
     1253                                    hdr_ptr += 2;
     1254                                    // apparently, if count_flag is set, entry is same as i
     1255                                    if (count_flag & 0x8000)
     1256                                        entry = i;
     1257                                    // only care about top 8 bits of 16-bit R, G, or B value
     1258                                    if (entry <= palette_count && entry >= 0)
     1259                                    {
     1260                                        palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0];
     1261                                        palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2];
     1262                                        palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4];
     1263                                        dprintf("QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n",
     1264                                                entry, palette_count,
     1265                                                palette_map[entry * 4 + 2],
     1266                                                palette_map[entry * 4 + 1],
     1267                                                palette_map[entry * 4 + 0]);
     1268                                    }
     1269                                    else
     1270                                        dprintf( "QT palette: skipped entry (out of count): %d of %d\n",
     1271                                                entry, palette_count);
     1272                                    hdr_ptr += 6;
    7951273                                }
    7961274                            }
    7971275                        }
     1276                        else
     1277                        {
     1278                            if (trak->fourcc == mmioFOURCC('a','v','c','1')) {
     1279                                if (trak->stream_header_len > 0xffffffff - sizeof(BITMAPINFOHEADERw)) {
     1280                                    dprintf("Invalid extradata size %d, skipping\n");
     1281                                    trak->stream_header_len = 0;
     1282                                }
     1283
     1284                                sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + trak->stream_header_len);
     1285                                memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + trak->stream_header_len);
     1286                                sh->bih->biSize=40  + trak->stream_header_len;
     1287                                memcpy(((unsigned char *)sh->bih)+40,  trak->stream_header, trak->stream_header_len);
     1288                                free (trak->stream_header);
     1289                                trak->stream_header_len = 0;
     1290                                trak->stream_header = NULL;
     1291                            } else {
     1292                                sh->bih=malloc(sizeof(BITMAPINFOHEADERw));
     1293                                memset(sh->bih,0,sizeof(BITMAPINFOHEADERw));
     1294                                sh->bih->biSize=40;
     1295                            }
     1296                        }
     1297                        sh->bih->biWidth=sh->disp_w;
     1298                        sh->bih->biHeight=sh->disp_h;
     1299                        sh->bih->biPlanes=0;
     1300                        sh->bih->biBitCount=depth;
     1301                        sh->bih->biCompression=trak->fourcc;
     1302                        sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight;
     1303
     1304                        dprintf( "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount);
     1305                        if(trak->tkdata_len>81)
     1306                            dprintf( "Display size: %d x %d\n",
     1307                                    trak->tkdata[77]|(trak->tkdata[76]<<8),
     1308                                    trak->tkdata[81]|(trak->tkdata[80]<<8));
     1309                        dprintf( "Fourcc: %.4s  Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43);
     1310
     1311                        //              if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){
     1312                        //                  // (auto)selected video track:
     1313                        //                  demuxer->video->id=priv->track_db;
     1314                        //                  demuxer->video->sh=sh; sh->ds=demuxer->video;
     1315                        //              }
     1316                        break;
    7981317                    }
    799 
    800                     switch (version) {
    801                     case 0:
    802                         adjust =  0; break;
    803                     case 1:
    804                         adjust = 48; break;
    805                     case 2:
    806                         adjust = 68; break;
     1318                    case MOV_TRAK_GENERIC:
     1319                        if (trak->fourcc == mmioFOURCC('m','p','4','s') ||
     1320                            trak->fourcc == mmioFOURCC('t','x','3','g') ||
     1321                            trak->fourcc == mmioFOURCC('t','e','x','t')) {
     1322                            sh_sub_t *sh = new_sh_sub(demuxer, priv->track_db);
     1323                            if (trak->fourcc == mmioFOURCC('m','p','4','s'))
     1324                                init_vobsub(sh, trak);
     1325                            else
     1326                                sh->type = 't';
     1327                        } else
     1328                            dprintf("Generic track - not completely understood! (id: %d)\n",
     1329                                    trak->id);
     1330                        /* XXX: Also this contains the FLASH data */
     1331#if 0
     1332                        {
     1333                            int pos = stream_tell(demuxer->stream);
     1334                            int i;
     1335                            int fd;
     1336                            char name[20];
     1337
     1338                            for (i=0; i<trak->samples_size; i++)
     1339                            {
     1340                                char buf[trak->samples[i].size];
     1341                                stream_seek(demuxer->stream, trak->samples[i].pos);
     1342                                snprintf((char *)&name[0], 20, "samp%d", i);
     1343                                fd = open((char *)&name[0], O_CREAT|O_WRONLY);
     1344                                stream_read(demuxer->stream, &buf[0], trak->samples[i].size);
     1345                                write(fd, &buf[0], trak->samples[i].size);
     1346                                close(fd);
     1347                            }
     1348                            for (i=0; i<trak->chunks_size; i++)
     1349                            {
     1350                                char buf[trak->length];
     1351                                stream_seek(demuxer->stream, trak->chunks[i].pos);
     1352                                snprintf((char *)&name[0], 20, "chunk%d", i);
     1353                                fd = open((char *)&name[0], O_CREAT|O_WRONLY);
     1354                                stream_read(demuxer->stream, &buf[0], trak->length);
     1355                                write(fd, &buf[0], trak->length);
     1356                                close(fd);
     1357                            }
     1358                            if (trak->samplesize > 0)
     1359                            {
     1360                                char *buf;
     1361
     1362                                buf = malloc(trak->samplesize);
     1363                                stream_seek(demuxer->stream, trak->chunks[0].pos);
     1364                                snprintf((char *)&name[0], 20, "trak%d", trak->id);
     1365                                fd = open((char *)&name[0], O_CREAT|O_WRONLY);
     1366                                stream_read(demuxer->stream, buf, trak->samplesize);
     1367                                write(fd, buf, trak->samplesize);
     1368                                close(fd);
     1369                            }
     1370                            stream_seek(demuxer->stream, pos);
     1371                        }
     1372#endif
     1373                        break;
    8071374                    default:
    808                         dprintf( "MOV: unknown sound atom version (%d); may not work!\n", version);
    809                         adjust = 68;
     1375                        dprintf( "Unknown track type found (type: %d)\n", trak->type);
     1376                        break;
    8101377                    }
    811                     if (trak->stdata_len >= 36 + adjust) {
    812                         int atom_len = char2int(trak->stdata,28+adjust);
    813                         switch(char2int(trak->stdata,32+adjust)) { // atom type
    814                         case MOV_FOURCC('e','s','d','s'): {
    815                             dprintf( "MOV: Found MPEG4 audio Elementary Stream Descriptor atom (%d)!\n", atom_len);
    816                             if(atom_len > 8) {
    817                                 esds_t esds;
    818                                 if(!mp4_parse_esds(&trak->stdata[36+adjust], atom_len-8, &esds)) {
    819                                     /* 0xdd is a "user private" id, not an official allocated id (see http://www.mp4ra.org/object.html),
    820                                      so perform some extra checks to be sure that this is really vorbis audio */
    821                                     if(esds.objectTypeId==0xdd && esds.streamType==0x15 && sh->format==0x6134706D && esds.decoderConfigLen > 8)
    822                                     {
    823                                         //vorbis audio
    824                                         unsigned char *buf[3];
    825                                         unsigned short sizes[3];
    826                                         int offset, len, k;
    827                                         unsigned char *ptr = esds.decoderConfig;
    828 
    829                                         if(ptr[0] != 0 || ptr[1] != 30) goto quit_vorbis_block; //wrong extradata layout
    830 
    831                                         offset = len = 0;
    832                                         for(k = 0; k < 3; k++)
    833                                         {
    834                                             sizes[k] = (ptr[offset]<<8) | ptr[offset+1];
    835                                             len += sizes[k];
    836                                             offset += 2;
    837                                             if(offset + sizes[k] > esds.decoderConfigLen)
    838                                             {
    839                                                 dprintf("MOV: ERROR!, not enough vorbis extradata to read: offset = %d, k=%d, size=%d, len: %d\n", offset, k, sizes[k], esds.decoderConfigLen);
    840                                                 goto quit_vorbis_block;
    841                                             }
    842                                             buf[k] = malloc(sizes[k]);
    843                                             if(!buf[k]) goto quit_vorbis_block;
    844                                             memcpy(buf[k], &ptr[offset], sizes[k]);
    845                                             offset += sizes[k];
    846                                         }
    847 
    848                                         sh->codecdata_len = len + len/255 + 64;
    849                                         sh->codecdata = malloc(sh->codecdata_len);
    850                                         ptr = sh->codecdata;
    851 
    852                                         ptr[0] = 2;
    853                                         offset = 1;
    854                                         offset += store_ughvlc(&ptr[offset], sizes[0]);
    855                                         offset += store_ughvlc(&ptr[offset], sizes[1]);
    856                                         for(k = 0; k < 3; k++)
    857                                         {
    858                                             memcpy(&ptr[offset], buf[k], sizes[k]);
    859                                             offset += sizes[k];
    860                                         }
    861 
    862                                         sh->codecdata_len = offset;
    863                                         sh->codecdata = realloc(sh->codecdata, offset);
    864                                         dprintf("demux_mov, vorbis extradata size: %d\n", offset);
    865                                         is_vorbis = 1;
    866                                     quit_vorbis_block:
    867                                         sh->format = mmioFOURCC('v', 'r', 'b', 's');
    868                                     }
    869                                     sh->i_bps = esds.avgBitrate/8;
    870 
    871                                     //                      printf("######## audio format = %d ########\n",esds.objectTypeId);
    872                                     if(esds.objectTypeId==MP4OTI_MPEG1Audio || esds.objectTypeId==MP4OTI_MPEG2AudioPart3)
    873                                         sh->format=0x55; // .mp3
    874                                     if(esds.objectTypeId==MP4OTI_13kVoice) { // 13K Voice, defined by 3GPP2
    875                                         sh->format=mmioFOURCC('Q', 'c', 'l', 'p');
    876                                         trak->nchannels=sh->channels=1;
    877                                         trak->samplebytes=sh->samplesize=1;
    878                                     }
    879 
    880                                     // dump away the codec specific configuration for the AAC decoder
    881                                     if(esds.decoderConfigLen){
    882                                         if( (esds.decoderConfig[0]>>3) == 29 )
    883                                             sh->format = 0x1d61346d; // request multi-channel mp3 decoder
    884                                         if(!is_vorbis)
    885                                         {
    886                                             sh->codecdata_len = esds.decoderConfigLen;
    887                                             sh->codecdata = (unsigned char *)malloc(sh->codecdata_len);
    888                                             memcpy(sh->codecdata, esds.decoderConfig, sh->codecdata_len);
    889                                         }
    890                                     }
    891                                 }
    892                                 mp4_free_esds(&esds); // freeup esds mem
    893 #if 0
    894                                 { FILE* f=fopen("esds.dat","wb");
    895                                     fwrite(&trak->stdata[36],atom_len-8,1,f);
    896                                 fclose(f); }
    897 #endif
    898                             }
    899                         } break;
    900                         case MOV_FOURCC('a','l','a','c'): {
    901                             dprintf( "MOV: Found alac atom (%d)!\n", atom_len);
    902                             if(atom_len > 8) {
    903                                 // copy all the atom (not only payload) for lavc alac decoder
    904                                 sh->codecdata_len = atom_len;
    905                                 sh->codecdata = (unsigned char *)malloc(sh->codecdata_len);
    906                                 memcpy(sh->codecdata, &trak->stdata[28], sh->codecdata_len);
    907                             }
    908                         } break;
    909                         case MOV_FOURCC('d','a','m','r'):
    910                             dprintf( "MOV: Found AMR audio atom %c%c%c%c (%d)!\n", trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust], atom_len);
    911                             if (atom_len>14) {
    912                                 dprintf( "mov: vendor: %c%c%c%c Version: %d\n",trak->stdata[36+adjust],trak->stdata[37+adjust],trak->stdata[38+adjust], trak->stdata[39+adjust],trak->stdata[40+adjust]);
    913                                 dprintf( "MOV: Modes set: %02x%02x\n",trak->stdata[41+adjust],trak->stdata[42+adjust]);
    914                                 dprintf( "MOV: Mode change period: %d Frames per sample: %d\n",trak->stdata[43+adjust],trak->stdata[44+adjust]);
    915                             }
    916                             break;
    917                         default:
    918                             dprintf( "MOV: Found unknown audio atom %c%c%c%c (%d)!\n",
    919                                     trak->stdata[32+adjust],trak->stdata[33+adjust],trak->stdata[34+adjust],trak->stdata[35+adjust],
    920                                     atom_len);
    921                         }
    922                     }
    923                     dprintf( "Fourcc: %.4s\n",(char *)&trak->fourcc);
    924 #if 0
    925                     { FILE* f=fopen("stdata.dat","wb");
    926                         fwrite(trak->stdata,trak->stdata_len,1,f);
    927                     fclose(f); }
    928                     { FILE* f=fopen("tkdata.dat","wb");
    929                         fwrite(trak->tkdata,trak->tkdata_len,1,f);
    930                     fclose(f); }
    931 #endif
    932                     // Emulate WAVEFORMATEX struct:
    933                     sh->wf=malloc(sizeof(WAVEFORMATEX) + (is_vorbis ? sh->codecdata_len : 0));
    934                     memset(sh->wf,0,sizeof(WAVEFORMATEX));
    935                     sh->wf->nChannels=sh->channels;
    936                     sh->wf->wBitsPerSample=(trak->stdata[18]<<8)+trak->stdata[19];
    937                     // sh->wf->nSamplesPerSec=trak->timescale;
    938                     sh->wf->nSamplesPerSec=sh->samplerate;
    939                     if(trak->stdata_len >= 44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){
    940                         //Audio header: samp/pack=4096 bytes/pack=743 bytes/frame=1486 bytes/samp=2
    941                         sh->wf->nAvgBytesPerSec=(sh->wf->nChannels*sh->wf->nSamplesPerSec*
    942                                                  char2int(trak->stdata,32)+char2int(trak->stdata,28)/2)
    943                             /char2int(trak->stdata,28);
    944                         sh->wf->nBlockAlign=char2int(trak->stdata,36);
    945                     } else {
    946                         sh->wf->nAvgBytesPerSec=sh->wf->nChannels*sh->wf->wBitsPerSample*sh->wf->nSamplesPerSec/8;
    947                         // workaround for ms11 ima4
    948                         if (sh->format == 0x1100736d && trak->stdata_len >= 36)
    949                             sh->wf->nBlockAlign=char2int(trak->stdata,36);
    950                     }
    951                     if(is_vorbis && sh->codecdata_len)
    952                     {
    953                         memcpy(sh->wf+1, sh->codecdata, sh->codecdata_len);
    954                         sh->wf->cbSize = sh->codecdata_len;
    955                     }
    956                     // Selection:
    957                     //          if(demuxer->audio->id==-1 || demuxer->audio->id==priv->track_db){
    958                     //              // (auto)selected audio track:
    959                     //              demuxer->audio->id=priv->track_db;
    960                     //              demuxer->audio->sh=sh; sh->ds=demuxer->audio;
    961                     //          }
     1378                    dprintf( "--------------\n");
     1379                    priv->track_db++;
     1380                    trak=NULL;
    9621381                    break;
    9631382                }
    964                 case MOV_TRAK_VIDEO: {
    965                     int i, entry;
    966                     int flag, start, count_flag, end, palette_count, gray;
    967                     int hdr_ptr = 76;  // the byte just after depth
    968                     unsigned char *palette_map;
    969                     sh_video_t* sh=new_sh_video(demuxer,priv->track_db);
    970                     int depth;
    971                     sh->format=trak->fourcc;
    972 
    973                     // crude video delay from editlist0 hack ::atm
    974                     if(trak->editlist_size>=1) {
    975                         if(trak->editlist[0].pos == -1) {
    976                             sh->stream_delay = (float)trak->editlist[0].dur/(float)priv->timescale;
    977                             dprintf("MOV: Initial Video-Delay: %.3f sec\n", sh->stream_delay);
    978                         }
    979                     }
    980 
    981                     if (trak->stdata_len < 78) {
    982                         dprintf("MOV: Invalid (%d bytes instead of >= 78) video trak desc\n",
    983                                 trak->stdata_len);
     1383#ifndef HAVE_ZLIB
     1384                case MOV_FOURCC('c','m','o','v'): {
     1385                    dprintf("MOV: got compressed header but have no zlib\n");
     1386                    return;
     1387                }
     1388#else
     1389                case MOV_FOURCC('m','o','o','v'):
     1390                case MOV_FOURCC('c','m','o','v'): {
     1391                    //      dprintf(MSGTR_MOVcomprhdr);
     1392                    lschunks(demuxer,level+1,pos+len,NULL);
     1393                    break;
     1394                }
     1395                case MOV_FOURCC('d','c','o','m'): {
     1396                    //      int temp=stream_read_dword(demuxer->stream);
     1397                    unsigned int algo=be2me_32(stream_read_dword(demuxer->stream));
     1398                    dprintf( "Compressed header uses %.4s algo!\n",(char *)&algo);
     1399                    break;
     1400                }
     1401                case MOV_FOURCC('c','m','v','d'): {
     1402                    //      int temp=stream_read_dword(demuxer->stream);
     1403                    unsigned int moov_sz=stream_read_dword(demuxer->stream);
     1404                    unsigned int cmov_sz=len-4;
     1405                    unsigned char* cmov_buf;
     1406                    unsigned char* moov_buf;
     1407                    int zret;
     1408                    z_stream zstrm;
     1409                    stream_t* backup;
     1410
     1411                    if (moov_sz > 0xffffffff - 16) {
     1412                        dprintf("Invalid cmvd atom size %d\n", moov_sz);
    9841413                        break;
    9851414                    }
    986                     depth = trak->stdata[75] | (trak->stdata[74] << 8);
    987                     //  stdata[]:
    988                     //  8   short       version
    989                     //  10  short       revision
    990                     //  12  int         vendor_id
    991                     //  16  int         temporal_quality
    992                     //  20  int         spatial_quality
    993                     //  24  short       width
    994                     //  26  short       height
    995                     //  28  int         h_dpi
    996                     //  32  int         v_dpi
    997                     //  36  int         0
    998                     //  40  short       frames_per_sample
    999                     //  42  char[4]     compressor_name
    1000                     //  74  short       depth
    1001                     //  76  short       color_table_id
    1002                     // additional atoms may follow,
    1003                     // eg esds atom from .MP4 files
    1004                     //      78  int             atom size
    1005                     //      82  char[4] atom type
    1006                     //  86  ...         atom data
    1007 
    1008                     {   ImageDescription* id=malloc(8+trak->stdata_len);  // safe
    1009                         trak->desc=id;
    1010                     id->idSize=8+trak->stdata_len;
    1011                     //          id->cType=bswap_32(trak->fourcc);
    1012                     id->cType=le2me_32(trak->fourcc);
    1013                     id->version=char2short(trak->stdata,8);
    1014                     id->revisionLevel=char2short(trak->stdata,10);
    1015                     id->vendor=char2int(trak->stdata,12);
    1016                     id->temporalQuality=char2int(trak->stdata,16);
    1017                     id->spatialQuality=char2int(trak->stdata,20);
    1018                     id->width=char2short(trak->stdata,24);
    1019                     id->height=char2short(trak->stdata,26);
    1020                     id->hRes=char2int(trak->stdata,28);
    1021                     id->vRes=char2int(trak->stdata,32);
    1022                     id->dataSize=char2int(trak->stdata,36);
    1023                     id->frameCount=char2short(trak->stdata,40);
    1024                     memcpy(&id->name,trak->stdata+42,32);
    1025                     id->depth=char2short(trak->stdata,74);
    1026                     id->clutID=char2short(trak->stdata,76);
    1027                     if(trak->stdata_len>78)     memcpy(((char*)&id->clutID)+2,trak->stdata+78,trak->stdata_len-78);
    1028                     sh->ImageDesc=id;
     1415                    cmov_buf=malloc(cmov_sz);
     1416                    moov_buf=malloc(moov_sz+16);
     1417                    dprintf( "Compressed header size: %d / %d\n",cmov_sz,moov_sz);
     1418
     1419                    stream_read(demuxer->stream,cmov_buf,cmov_sz);
     1420
     1421                    zstrm.zalloc          = (alloc_func)0;
     1422                    zstrm.zfree           = (free_func)0;
     1423                    zstrm.opaque          = (voidpf)0;
     1424                    zstrm.next_in         = cmov_buf;
     1425                    zstrm.avail_in        = cmov_sz;
     1426                    zstrm.next_out        = moov_buf;
     1427                    zstrm.avail_out       = moov_sz;
     1428
     1429                    zret = inflateInit(&zstrm);
     1430                    if (zret != Z_OK)
     1431                    { dprintf( "QT cmov: inflateInit err %d\n",zret);
     1432                        return;
     1433                    }
     1434                    zret = inflate(&zstrm, Z_NO_FLUSH);
     1435                    if ((zret != Z_OK) && (zret != Z_STREAM_END))
     1436                    { dprintf( "QT cmov inflate: ERR %d\n",zret);
     1437                        return;
     1438                    }
    10291439#if 0
    1030                     {   FILE *f=fopen("ImageDescription","wb");
    1031                         fwrite(id,id->idSize,1,f);
    1032                     fclose(f);
     1440                    else {
     1441                        FILE *DecOut;
     1442                        DecOut = fopen("Out.bin", "w");
     1443                        fwrite(moov_buf, 1, moov_sz, DecOut);
     1444                        fclose(DecOut);
    10331445                    }
    10341446#endif
    1035                     }
    1036 
    1037                     if(trak->stdata_len >= 86) { // extra atoms found
    1038                         int pos=78;
    1039                         int atom_len;
    1040                         while(pos+8<=trak->stdata_len &&
    1041                               (pos+(atom_len=char2int(trak->stdata,pos)))<=trak->stdata_len){
    1042                             switch(char2int(trak->stdata,pos+4)) { // switch atom type
    1043                             case MOV_FOURCC('g','a','m','a'):
    1044                                 // intfp with gamma value at which movie was captured
    1045                                 // can be used to gamma correct movie display
    1046                                 dprintf( "MOV: Found unsupported Gamma-Correction movie atom (%d)!\n",
    1047                                         atom_len);
    1048                                 break;
    1049                             case MOV_FOURCC('f','i','e','l'):
    1050                                 // 2 char-values (8bit int) that specify field handling
    1051                                 // see the Apple's QuickTime Fileformat PDF for more info
    1052                                 dprintf( "MOV: Found unsupported Field-Handling movie atom (%d)!\n",
    1053                                         atom_len);
    1054                                 break;
    1055                             case MOV_FOURCC('m','j','q','t'):
    1056                                 // Motion-JPEG default quantization table
    1057                                 dprintf( "MOV: Found unsupported MJPEG-Quantization movie atom (%d)!\n",
    1058                                         atom_len);
    1059                                 break;
    1060                             case MOV_FOURCC('m','j','h','t'):
    1061                                 // Motion-JPEG default huffman table
    1062                                 dprintf( "MOV: Found unsupported MJPEG-Huffman movie atom (%d)!\n",
    1063                                         atom_len);
    1064                                 break;
    1065                             case MOV_FOURCC('e','s','d','s'):
    1066                                 // MPEG4 Elementary Stream Descriptor header
    1067                                 dprintf( "MOV: Found MPEG4 movie Elementary Stream Descriptor atom (%d)!\n", atom_len);
    1068                                 // add code here to save esds header of length atom_len-8
    1069                                 // beginning at stdata[86] to some variable to pass it
    1070                                 // on to the decoder ::atmos
    1071                                 if(atom_len > 8) {
    1072                                     esds_t esds;
    1073                                     if(!mp4_parse_esds(trak->stdata+pos+8, atom_len-8, &esds)) {
    1074 
    1075                                         if(esds.objectTypeId==MP4OTI_MPEG2VisualSimple || esds.objectTypeId==MP4OTI_MPEG2VisualMain ||
    1076                                            esds.objectTypeId==MP4OTI_MPEG2VisualSNR || esds.objectTypeId==MP4OTI_MPEG2VisualSpatial ||
    1077                                            esds.objectTypeId==MP4OTI_MPEG2VisualHigh || esds.objectTypeId==MP4OTI_MPEG2Visual422)
    1078                                             sh->format=mmioFOURCC('m', 'p', 'g', '2');
    1079                                         else if(esds.objectTypeId==MP4OTI_MPEG1Visual)
    1080                                             sh->format=mmioFOURCC('m', 'p', 'g', '1');
    1081 
    1082                                         // dump away the codec specific configuration for the AAC decoder
    1083                                         trak->stream_header_len = esds.decoderConfigLen;
    1084                                         trak->stream_header = (unsigned char *)malloc(trak->stream_header_len);
    1085                                         memcpy(trak->stream_header, esds.decoderConfig, trak->stream_header_len);
     1447                    if(moov_sz != zstrm.total_out)
     1448                        dprintf( "Warning! moov size differs cmov: %d  zlib: %ld\n",moov_sz,zstrm.total_out);
     1449                    zret = inflateEnd(&zstrm);
     1450
     1451                    backup=demuxer->stream;
     1452                    demuxer->stream=new_memory_stream(moov_buf,moov_sz);
     1453                    stream_skip(demuxer->stream,8);
     1454                    lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov'
     1455                    //free_stream(demuxer->stream);
     1456                    demuxer->stream=backup;
     1457                    free(cmov_buf);
     1458                    free(moov_buf);
     1459                    break;
     1460                }
     1461#endif
     1462                case MOV_FOURCC('u','d','t','a'):
     1463                    {
     1464                        unsigned int udta_id;
     1465                        off_t udta_len;
     1466                        off_t udta_size = len;
     1467
     1468                        dprintf( "mov: user data record found\n");
     1469                        dprintf( "Quicktime Clip Info:\n");
     1470
     1471                        while((len > 8) && (udta_size > 8))
     1472                        {
     1473                            udta_len = stream_read_dword(demuxer->stream);
     1474                            udta_id = stream_read_dword(demuxer->stream);
     1475                            udta_size -= 8;
     1476                            dprintf( "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len);
     1477                            switch (udta_id)
     1478                            {
     1479                            case MOV_FOURCC(0xa9,'c','p','y'):
     1480                            case MOV_FOURCC(0xa9,'d','a','y'):
     1481                            case MOV_FOURCC(0xa9,'d','i','r'):
     1482                                /* 0xa9,'e','d','1' - '9' : edit timestamps */
     1483                            case MOV_FOURCC(0xa9,'f','m','t'):
     1484                            case MOV_FOURCC(0xa9,'i','n','f'):
     1485                            case MOV_FOURCC(0xa9,'p','r','d'):
     1486                            case MOV_FOURCC(0xa9,'p','r','f'):
     1487                            case MOV_FOURCC(0xa9,'r','e','q'):
     1488                            case MOV_FOURCC(0xa9,'s','r','c'):
     1489                            case MOV_FOURCC('n','a','m','e'):
     1490                            case MOV_FOURCC(0xa9,'n','a','m'):
     1491                            case MOV_FOURCC(0xa9,'A','R','T'):
     1492                            case MOV_FOURCC(0xa9,'c','m','t'):
     1493                            case MOV_FOURCC(0xa9,'a','u','t'):
     1494                            case MOV_FOURCC(0xa9,'s','w','r'):
     1495                                {
     1496                                    off_t text_len = stream_read_word(demuxer->stream);
     1497                                    char text[text_len+2+1];
     1498                                    stream_read(demuxer->stream, (char *)&text, text_len+2);
     1499                                    text[text_len+2] = 0x0;
     1500                                    switch(udta_id)
     1501                                    {
     1502                                    case MOV_FOURCC(0xa9,'a','u','t'):
     1503                                        demux_info_add(demuxer, "author", &text[2]);
     1504                                        dprintf( " Author: %s\n", &text[2]);
     1505                                        break;
     1506                                    case MOV_FOURCC(0xa9,'c','p','y'):
     1507                                        demux_info_add(demuxer, "copyright", &text[2]);
     1508                                        dprintf( " Copyright: %s\n", &text[2]);
     1509                                        break;
     1510                                    case MOV_FOURCC(0xa9,'i','n','f'):
     1511                                        dprintf( " Info: %s\n", &text[2]);
     1512                                        break;
     1513                                    case MOV_FOURCC('n','a','m','e'):
     1514                                    case MOV_FOURCC(0xa9,'n','a','m'):
     1515                                        demux_info_add(demuxer, "name", &text[2]);
     1516                                        dprintf( " Name: %s\n", &text[2]);
     1517                                        break;
     1518                                    case MOV_FOURCC(0xa9,'A','R','T'):
     1519                                        dprintf( " Artist: %s\n", &text[2]);
     1520                                        break;
     1521                                    case MOV_FOURCC(0xa9,'d','i','r'):
     1522                                        dprintf( " Director: %s\n", &text[2]);
     1523                                        break;
     1524                                    case MOV_FOURCC(0xa9,'c','m','t'):
     1525                                        demux_info_add(demuxer, "comments", &text[2]);
     1526                                        dprintf( " Comment: %s\n", &text[2]);
     1527                                        break;
     1528                                    case MOV_FOURCC(0xa9,'r','e','q'):
     1529                                        dprintf( " Requirements: %s\n", &text[2]);
     1530                                        break;
     1531                                    case MOV_FOURCC(0xa9,'s','w','r'):
     1532                                        demux_info_add(demuxer, "encoder", &text[2]);
     1533                                        dprintf( " Software: %s\n", &text[2]);
     1534                                        break;
     1535                                    case MOV_FOURCC(0xa9,'d','a','y'):
     1536                                        dprintf( " Creation timestamp: %s\n", &text[2]);
     1537                                        break;
     1538                                    case MOV_FOURCC(0xa9,'f','m','t'):
     1539                                        dprintf( " Format: %s\n", &text[2]);
     1540                                        break;
     1541                                    case MOV_FOURCC(0xa9,'p','r','d'):
     1542                                        dprintf( " Producer: %s\n", &text[2]);
     1543                                        break;
     1544                                    case MOV_FOURCC(0xa9,'p','r','f'):
     1545                                        dprintf( " Performer(s): %s\n", &text[2]);
     1546                                        break;
     1547                                    case MOV_FOURCC(0xa9,'s','r','c'):
     1548                                        dprintf( " Source providers: %s\n", &text[2]);
     1549                                        break;
    10861550                                    }
    1087                                     mp4_free_esds(&esds); // freeup esds mem
     1551                                    udta_size -= 4+text_len;
     1552                                    break;
    10881553                                }
    1089                                 break;
    1090                             case MOV_FOURCC('a','v','c','C'):
    1091                                 // AVC decoder configuration record
    1092                                 dprintf( "MOV: AVC decoder configuration record atom (%d)!\n", atom_len);
    1093                                 if(atom_len > 8) {
    1094                                     int i, poffs, cnt;
    1095                                     // Parse some parts of avcC, just for fun :)
    1096                                     // real parsing is done by avc1 decoder
    1097                                     dprintf( "MOV: avcC version: %d\n", *(trak->stdata+pos+8));
    1098                                     if (*(trak->stdata+pos+8) != 1)
    1099                                         dprintf( "MOV: unknown avcC version (%d). Expexct problems.\n", *(trak->stdata+pos+9));
    1100                                     dprintf( "MOV: avcC profile: %d\n", *(trak->stdata+pos+9));
    1101                                     dprintf( "MOV: avcC profile compatibility: %d\n", *(trak->stdata+pos+10));
    1102                                     dprintf( "MOV: avcC level: %d\n", *(trak->stdata+pos+11));
    1103                                     dprintf( "MOV: avcC nal length size: %d\n", ((*(trak->stdata+pos+12))&0x03)+1);
    1104                                     dprintf( "MOV: avcC number of sequence param sets: %d\n", cnt = (*(trak->stdata+pos+13) & 0x1f));
    1105                                     poffs = pos + 14;
    1106                                     for (i = 0; i < cnt; i++) {
    1107                                         dprintf( "MOV: avcC sps %d have length %d\n", i, BE_16(trak->stdata+poffs));
    1108                                         poffs += BE_16(trak->stdata+poffs) + 2;
    1109                                     }
    1110                                     dprintf( "MOV: avcC number of picture param sets: %d\n", *(trak->stdata+poffs));
    1111                                     poffs++;
    1112                                     for (i = 0; i < cnt; i++) {
    1113                                         dprintf( "MOV: avcC pps %d have length %d\n", i, BE_16(trak->stdata+poffs));
    1114                                         poffs += BE_16(trak->stdata+poffs) + 2;
    1115                                     }
    1116                                     // Copy avcC for the AVC decoder
    1117                                     // This data will be put in extradata below, where BITMAPINFOHEADER is created
    1118                                     trak->stream_header_len = atom_len-8;
    1119                                     trak->stream_header = (unsigned char *)malloc(trak->stream_header_len);
    1120                                     memcpy(trak->stream_header, trak->stdata+pos+8, trak->stream_header_len);
    1121                                 }
    1122                                 break;
    1123                             case MOV_FOURCC('d','2','6','3'):
    1124                                 dprintf( "MOV: Found H.263 decoder atom %c%c%c%c (%d)!\n", trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],atom_len);
    1125                                 if (atom_len>10)
    1126                                     dprintf( "MOV: Vendor: %c%c%c%c H.263 level: %d H.263 profile: %d \n", trak->stdata[pos+8],trak->stdata[pos+9],trak->stdata[pos+10],trak->stdata[pos+11],trak->stdata[pos+12],trak->stdata[pos+13]);
    1127                                 break;
    1128                             case 0:
    1129                                 break;
     1554                                /* some other shits:    WLOC - window location,
     1555                                 LOOP - looping style,
     1556                                 SelO - play only selected frames
     1557                                 AllF - play all frames
     1558                                 */
     1559                            case MOV_FOURCC('W','L','O','C'):
     1560                            case MOV_FOURCC('L','O','O','P'):
     1561                            case MOV_FOURCC('S','e','l','O'):
     1562                            case MOV_FOURCC('A','l','l','F'):
    11301563                            default:
    1131                                 dprintf( "MOV: Found unknown movie atom %c%c%c%c (%d)!\n",
    1132                                         trak->stdata[pos+4],trak->stdata[pos+5],trak->stdata[pos+6],trak->stdata[pos+7],
    1133                                         atom_len);
    1134                             }
    1135                             if(atom_len<8) break;
    1136                             pos+=atom_len;
    1137                             //             printf("pos=%d max=%d\n",pos,trak->stdata_len);
    1138                         }
    1139                     }
    1140                     sh->fps=trak->timescale/
    1141                         ((trak->durmap_size>=1)?(float)trak->durmap[0].dur:1);
    1142                     sh->frametime=1.0f/sh->fps;
    1143 
    1144                     sh->disp_w=trak->stdata[25]|(trak->stdata[24]<<8);
    1145                     sh->disp_h=trak->stdata[27]|(trak->stdata[26]<<8);
    1146                     // if image size is zero, fallback to display size
    1147                     if(!sh->disp_w && !sh->disp_h) {
    1148                         sh->disp_w=trak->tkdata[77]|(trak->tkdata[76]<<8);
    1149                         sh->disp_h=trak->tkdata[81]|(trak->tkdata[80]<<8);
    1150                     } else if(sh->disp_w!=(trak->tkdata[77]|(trak->tkdata[76]<<8))){
    1151                         // codec and display width differ... use display one for aspect
    1152                         sh->aspect=trak->tkdata[77]|(trak->tkdata[76]<<8);
    1153                         sh->aspect/=trak->tkdata[81]|(trak->tkdata[80]<<8);
    1154                     }
    1155 
    1156                     if(depth>32+8) printf("*** depth = 0x%X\n",depth);
    1157 
    1158                     // palettized?
    1159                     gray = 0;
    1160                     if (depth > 32) { depth&=31; gray = 1; } // depth > 32 means grayscale
    1161                     if ((depth == 2) || (depth == 4) || (depth == 8))
    1162                         palette_count = (1 << depth);
    1163                     else
    1164                         palette_count = 0;
    1165 
    1166                     // emulate BITMAPINFOHEADER:
    1167                     if (palette_count)
    1168                     {
    1169                         sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + palette_count * 4);
    1170                         memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + palette_count * 4);
    1171                         sh->bih->biSize=40 + palette_count * 4;
    1172                         // fetch the relevant fields
    1173                         flag = BE_16(&trak->stdata[hdr_ptr]);
    1174                         hdr_ptr += 2;
    1175                         start = BE_32(&trak->stdata[hdr_ptr]);
    1176                         hdr_ptr += 4;
    1177                         count_flag = BE_16(&trak->stdata[hdr_ptr]);
    1178                         hdr_ptr += 2;
    1179                         end = BE_16(&trak->stdata[hdr_ptr]);
    1180                         hdr_ptr += 2;
    1181                         palette_map = (unsigned char *)sh->bih + 40;
    1182                         dprintf( "Allocated %d entries for palette\n",
    1183                                 palette_count);
    1184                         dprintf( "QT palette: start: %x, end: %x, count flag: %d, flags: %x\n",
    1185                                 start, end, count_flag, flag);
    1186 
    1187                         /* XXX: problems with sample (statunit6.mov) with flag&0x4 set! - alex*/
    1188 
    1189                         // load default palette
    1190                         if (flag & 0x08)
    1191                         {
    1192                             if (gray)
    1193                             {
    1194                                 dprintf( "Using default QT grayscale palette\n");
    1195                                 if (palette_count == 16)
    1196                                     memcpy(palette_map, qt_default_grayscale_palette_16, 16 * 4);
    1197                                 else if (palette_count == 256) {
    1198                                     memcpy(palette_map, qt_default_grayscale_palette_256, 256 * 4);
    1199                                     if (trak->fourcc == mmioFOURCC('c','v','i','d')) {
    1200                                         int i;
    1201                                         // Hack for grayscale CVID, negative palette
    1202                                         // If you have samples where this is not required contact me (rxt)
    1203                                         dprintf( "MOV: greyscale cvid with default palette,"
    1204                                                 " enabling negative palette hack.\n");
    1205                                         for (i = 0; i < 256 * 4; i++)
    1206                                             palette_map[i] = palette_map[i] ^ 0xff;
     1564                                {
     1565                                    if( udta_len>udta_size)
     1566                                        udta_len=udta_size;
     1567                                    {
     1568                                        char dump[udta_len-4];
     1569                                        stream_read(demuxer->stream, (char *)&dump, udta_len-4-4);
     1570                                        udta_size -= udta_len;
    12071571                                    }
    12081572                                }
    12091573                            }
    1210                             else
    1211                             {
    1212                                 dprintf( "Using default QT colour palette\n");
    1213                                 if (palette_count == 4)
    1214                                     memcpy(palette_map, qt_default_palette_4, 4 * 4);
    1215                                 else if (palette_count == 16)
    1216                                     memcpy(palette_map, qt_default_palette_16, 16 * 4);
    1217                                 else if (palette_count == 256)
    1218                                     memcpy(palette_map, qt_default_palette_256, 256 * 4);
    1219                             }
    12201574                        }
    1221                         // load palette from file
    1222                         else
    1223                         {
    1224                             dprintf( "Loading palette from file\n");
    1225                             for (i = start; i <= end; i++)
    1226                             {
    1227                                 entry = BE_16(&trak->stdata[hdr_ptr]);
    1228                                 hdr_ptr += 2;
    1229                                 // apparently, if count_flag is set, entry is same as i
    1230                                 if (count_flag & 0x8000)
    1231                                     entry = i;
    1232                                 // only care about top 8 bits of 16-bit R, G, or B value
    1233                                 if (entry <= palette_count && entry >= 0)
    1234                                 {
    1235                                     palette_map[entry * 4 + 2] = trak->stdata[hdr_ptr + 0];
    1236                                     palette_map[entry * 4 + 1] = trak->stdata[hdr_ptr + 2];
    1237                                     palette_map[entry * 4 + 0] = trak->stdata[hdr_ptr + 4];
    1238                                     dprintf("QT palette: added entry: %d of %d (colors: R:%x G:%x B:%x)\n",
    1239                                             entry, palette_count,
    1240                                             palette_map[entry * 4 + 2],
    1241                                             palette_map[entry * 4 + 1],
    1242                                             palette_map[entry * 4 + 0]);
    1243                                 }
    1244                                 else
    1245                                     dprintf( "QT palette: skipped entry (out of count): %d of %d\n",
    1246                                             entry, palette_count);
    1247                                 hdr_ptr += 6;
    1248                             }
    1249                         }
    1250                     }
    1251                     else
    1252                     {
    1253                         if (trak->fourcc == mmioFOURCC('a','v','c','1')) {
    1254                             if (trak->stream_header_len > 0xffffffff - sizeof(BITMAPINFOHEADERw)) {
    1255                                 dprintf("Invalid extradata size %d, skipping\n");
    1256                                 trak->stream_header_len = 0;
    1257                             }
    1258 
    1259                             sh->bih=malloc(sizeof(BITMAPINFOHEADERw) + trak->stream_header_len);
    1260                             memset(sh->bih,0,sizeof(BITMAPINFOHEADERw) + trak->stream_header_len);
    1261                             sh->bih->biSize=40  + trak->stream_header_len;
    1262                             memcpy(((unsigned char *)sh->bih)+40,  trak->stream_header, trak->stream_header_len);
    1263                             free (trak->stream_header);
    1264                             trak->stream_header_len = 0;
    1265                             trak->stream_header = NULL;
    1266                         } else {
    1267                             sh->bih=malloc(sizeof(BITMAPINFOHEADERw));
    1268                             memset(sh->bih,0,sizeof(BITMAPINFOHEADERw));
    1269                             sh->bih->biSize=40;
    1270                         }
    1271                     }
    1272                     sh->bih->biWidth=sh->disp_w;
    1273                     sh->bih->biHeight=sh->disp_h;
    1274                     sh->bih->biPlanes=0;
    1275                     sh->bih->biBitCount=depth;
    1276                     sh->bih->biCompression=trak->fourcc;
    1277                     sh->bih->biSizeImage=sh->bih->biWidth*sh->bih->biHeight;
    1278 
    1279                     dprintf( "Image size: %d x %d (%d bpp)\n",sh->disp_w,sh->disp_h,sh->bih->biBitCount);
    1280                     if(trak->tkdata_len>81)
    1281                         dprintf( "Display size: %d x %d\n",
    1282                                 trak->tkdata[77]|(trak->tkdata[76]<<8),
    1283                                 trak->tkdata[81]|(trak->tkdata[80]<<8));
    1284                     dprintf( "Fourcc: %.4s  Codec: '%.*s'\n",(char *)&trak->fourcc,trak->stdata[42]&31,trak->stdata+43);
    1285 
    1286                     //          if(demuxer->video->id==-1 || demuxer->video->id==priv->track_db){
    1287                     //              // (auto)selected video track:
    1288                     //              demuxer->video->id=priv->track_db;
    1289                     //              demuxer->video->sh=sh; sh->ds=demuxer->video;
    1290                     //          }
     1575                        break;
     1576                    } /* eof udta */
     1577                default:
     1578                    id = be2me_32(id);
     1579                    dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
     1580                } /* endof switch */
     1581            } /* endof else */
     1582
     1583            pos+=len+8;
     1584            if(pos>=endpos) break;
     1585            if(!stream_seek(demuxer->stream,pos)) break;
     1586        }
     1587    }
     1588
     1589    static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id,
     1590                               off_t pos, off_t len, mov_track_t* trak)
     1591    {
     1592        switch(id) {
     1593        case MOV_FOURCC('m','d','a','t'): {
     1594            dprintf("Hmm, strange MOV, parsing mdat in lschunks?\n");
     1595            return -1;
     1596        }
     1597        case MOV_FOURCC('f','r','e','e'):
     1598        case MOV_FOURCC('u','d','t','a'):
     1599            /* here not supported :p */
     1600            break;
     1601        case MOV_FOURCC('t','k','h','d'): {
     1602            dprintf("MOV: %*sTrack header!\n", level, "");
     1603            // read codec data
     1604            trak->tkdata_len = len;
     1605            trak->tkdata = malloc(trak->tkdata_len);
     1606            stream_read(demuxer->stream, trak->tkdata, trak->tkdata_len);
     1607            /*
     1608             0  1 Version
     1609             1  3 Flags
     1610             4  4 Creation time
     1611             8  4 Modification time
     1612             12 4 Track ID
     1613             16 4 Reserved
     1614             20 4 Duration
     1615             24 8 Reserved
     1616             32 2 Layer
     1617             34 2 Alternate group
     1618             36 2 Volume
     1619             38 2 Reserved
     1620             40 36 Matrix structure
     1621             76 4 Track width
     1622             80 4 Track height
     1623             */
     1624            dprintf(
     1625                    "tkhd len=%d ver=%d flags=0x%X id=%d dur=%d lay=%d vol=%d\n",
     1626                    trak->tkdata_len, trak->tkdata[0], trak->tkdata[1],
     1627                    char2int(trak->tkdata, 12), // id
     1628                    char2int(trak->tkdata, 20), // duration
     1629                    char2short(trak->tkdata, 32), // layer
     1630                    char2short(trak->tkdata, 36)); // volume
     1631            break;
     1632        }
     1633        case MOV_FOURCC('m','d','h','d'): {
     1634            dprintf( "MOV: %*sMedia header!\n", level, "");
     1635            int version = stream_read_char(demuxer->stream);
     1636            stream_skip(demuxer->stream, (version == 1) ? 19 : 11);
     1637            // read timescale
     1638            trak->timescale = stream_read_dword(demuxer->stream);
     1639            // read length
     1640            if (version == 1)
     1641                trak->length = stream_read_qword(demuxer->stream);
     1642            else
     1643                trak->length = stream_read_dword(demuxer->stream);
     1644            break;
     1645        }
     1646        case MOV_FOURCC('h','d','l','r'): {
     1647            unsigned int tmp = stream_read_dword(demuxer->stream);
     1648            unsigned int type = stream_read_dword_le(demuxer->stream);
     1649            unsigned int subtype = stream_read_dword_le(demuxer->stream);
     1650            unsigned int manufact = stream_read_dword_le(demuxer->stream);
     1651            unsigned int comp_flags = stream_read_dword(demuxer->stream);
     1652            unsigned int comp_mask = stream_read_dword(demuxer->stream);
     1653            int len = stream_read_char(demuxer->stream);
     1654            char* str = malloc(len + 1);
     1655            stream_read(demuxer->stream, str, len);
     1656            str[len] = 0;
     1657            dprintf(
     1658                    "MOV: %*sHandler header: %.4s/%.4s (%.4s) %s\n", level, "",
     1659                    (char *)&type, (char *)&subtype, (char *)&manufact, str);
     1660            free(str);
     1661            switch(bswap_32(type)) {
     1662            case MOV_FOURCC('m','h','l','r'):
     1663                trak->media_handler = bswap_32(subtype);
     1664                break;
     1665            case MOV_FOURCC('d','h','l','r'):
     1666                trak->data_handler = bswap_32(subtype);
     1667                break;
     1668            default:
     1669                dprintf(
     1670                        "MOV: unknown handler class: 0x%X (%.4s)\n",
     1671                        bswap_32(type), (char *)&type);
     1672            }
     1673            break;
     1674        }
     1675        case MOV_FOURCC('v','m','h','d'): {
     1676            dprintf("MOV: %*sVideo header!\n", level, "");
     1677            trak->type = MOV_TRAK_VIDEO;
     1678            // read video data
     1679            break;
     1680        }
     1681        case MOV_FOURCC('s','m','h','d'): {
     1682            dprintf("MOV: %*sSound header!\n", level, "");
     1683            trak->type = MOV_TRAK_AUDIO;
     1684            // read audio data
     1685            break;
     1686        }
     1687        case MOV_FOURCC('g','m','h','d'): {
     1688            dprintf("MOV: %*sGeneric header!\n", level, "");
     1689            trak->type = MOV_TRAK_GENERIC;
     1690            break;
     1691        }
     1692        case MOV_FOURCC('n','m','h','d'): {
     1693            dprintf("MOV: %*sGeneric header!\n", level, "");
     1694            trak->type = MOV_TRAK_GENERIC;
     1695            break;
     1696        }
     1697        case MOV_FOURCC('s','t','s','d'): {
     1698            int i = stream_read_dword(demuxer->stream); // temp!
     1699            int count = stream_read_dword(demuxer->stream);
     1700            dprintf("MOV: %*sDescription list! (cnt:%d)\n",
     1701                    level, "", count);
     1702            for (i = 0; i < count; i++) {
     1703                off_t pos = stream_tell(demuxer->stream);
     1704                off_t len = stream_read_dword(demuxer->stream);
     1705                unsigned int fourcc = stream_read_dword_le(demuxer->stream);
     1706                /* some files created with Broadcast 2000 (e.g. ilacetest.mov)
     1707                 contain raw I420 video but have a yv12 fourcc */
     1708                if (fourcc == mmioFOURCC('y','v','1','2'))
     1709                    fourcc = mmioFOURCC('I','4','2','0');
     1710                if (len < 8)
     1711                    break; // error
     1712                dprintf("MOV: %*s desc #%d: %.4s  (%"PRId64" bytes)\n", level, "",
     1713                        i, (char *)&fourcc, (int64_t)len - 16);
     1714                if (fourcc != trak->fourcc && i)
     1715                    dprintf("MOW: warning - different fourcc\n");
     1716                //      if(!i)
     1717                {
     1718                    trak->fourcc = fourcc;
     1719                    // read type specific (audio/video/time/text etc) header
     1720                    // NOTE: trak type is not yet known at this point :(((
     1721                    trak->stdata_len = len - 8;
     1722                    trak->stdata = malloc(trak->stdata_len);
     1723                    stream_read(demuxer->stream, trak->stdata, trak->stdata_len);
     1724                }
     1725                if (!stream_seek(demuxer->stream, pos + len))
     1726                    break;
     1727            }
     1728            break;
     1729        }
     1730        case MOV_FOURCC('s','t','t','s'): {
     1731            int temp = stream_read_dword(demuxer->stream);
     1732            int len = stream_read_dword(demuxer->stream);
     1733            int i;
     1734            unsigned int pts = 0;
     1735            dprintf("MOV: %*sSample duration table! (%d blocks)\n", level, "",
     1736                    len);
     1737            trak->durmap = calloc(len, sizeof(mov_durmap_t));
     1738            trak->durmap_size = len;
     1739            for (i = 0; i < len; i++) {
     1740                trak->durmap[i].num = stream_read_dword(demuxer->stream);
     1741                trak->durmap[i].dur = stream_read_dword(demuxer->stream);
     1742                pts += trak->durmap[i].num * trak->durmap[i].dur;
     1743            }
     1744            if (trak->length != pts)
     1745                dprintf( "Warning! pts=%d  length=%d\n",
     1746                        pts, trak->length);
     1747            break;
     1748        }
     1749        case MOV_FOURCC('s','t','s','c'): {
     1750            int temp = stream_read_dword(demuxer->stream);
     1751            int len = stream_read_dword(demuxer->stream);
     1752            int ver = (temp << 24);
     1753            int flags = (temp << 16) | (temp << 8) | temp;
     1754            int i;
     1755            dprintf("MOV: %*sSample->Chunk mapping table!  (%d blocks) (ver:%d,flags:%d)\n", level, "",
     1756                    len, ver, flags);
     1757            // read data:
     1758            trak->chunkmap_size = len;
     1759            trak->chunkmap = calloc(len, sizeof(mov_chunkmap_t));
     1760            for (i = 0; i < len; i++) {
     1761                trak->chunkmap[i].first = stream_read_dword(demuxer->stream) - 1;
     1762                trak->chunkmap[i].spc = stream_read_dword(demuxer->stream);
     1763                trak->chunkmap[i].sdid = stream_read_dword(demuxer->stream);
     1764            }
     1765            break;
     1766        }
     1767        case MOV_FOURCC('s','t','s','z'): {
     1768            int temp = stream_read_dword(demuxer->stream);
     1769            int ss=stream_read_dword(demuxer->stream);
     1770            int ver = (temp << 24);
     1771            int flags = (temp << 16) | (temp << 8) | temp;
     1772            int entries = stream_read_dword(demuxer->stream);
     1773            int i;
     1774            dprintf(
     1775                    "MOV: %*sSample size table! (entries=%d ss=%d) (ver:%d,flags:%d)\n", level, "",
     1776                    entries, ss, ver, flags);
     1777            trak->samplesize = ss;
     1778            if (!ss) {
     1779                // variable samplesize
     1780                trak->samples = realloc_struct(trak->samples, entries, sizeof(mov_sample_t));
     1781                trak->samples_size = entries;
     1782                for (i = 0; i < entries; i++)
     1783                    trak->samples[i].size = stream_read_dword(demuxer->stream);
     1784            }
     1785            break;
     1786        }
     1787        case MOV_FOURCC('s','t','c','o'): {
     1788            int temp = stream_read_dword(demuxer->stream);
     1789            int len = stream_read_dword(demuxer->stream);
     1790            int i;
     1791            dprintf(
     1792                    "MOV: %*sChunk offset table! (%d chunks)\n", level, "",
     1793                    len);
     1794            // extend array if needed:
     1795            if (len > trak->chunks_size) {
     1796                trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t));
     1797                trak->chunks_size = len;
     1798            }
     1799            // read elements:
     1800            for(i = 0; i < len; i++)
     1801                trak->chunks[i].pos = stream_read_dword(demuxer->stream);
     1802            break;
     1803        }
     1804        case MOV_FOURCC('c','o','6','4'): {
     1805            int temp = stream_read_dword(demuxer->stream);
     1806            int len = stream_read_dword(demuxer->stream);
     1807            int i;
     1808            dprintf(
     1809                    "MOV: %*s64bit chunk offset table! (%d chunks)\n", level, "",
     1810                    len);
     1811            // extend array if needed:
     1812            if (len > trak->chunks_size) {
     1813                trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t));
     1814                trak->chunks_size = len;
     1815            }
     1816            // read elements:
     1817            for (i = 0; i < len; i++) {
     1818#ifndef _LARGEFILE_SOURCE
     1819                if (stream_read_dword(demuxer->stream) != 0)
     1820                    dprintf( "Chunk %d has got 64bit address, but you've MPlayer compiled without LARGEFILE support!\n", i);
     1821                trak->chunks[i].pos = stream_read_dword(demuxer->stream);
     1822#else
     1823                trak->chunks[i].pos = stream_read_qword(demuxer->stream);
     1824#endif
     1825            }
     1826            break;
     1827        }
     1828        case MOV_FOURCC('s','t','s','s'): {
     1829            int temp = stream_read_dword(demuxer->stream);
     1830            int entries = stream_read_dword(demuxer->stream);
     1831            int ver = (temp << 24);
     1832            int flags = (temp << 16) | (temp<<8) | temp;
     1833            int i;
     1834            dprintf(
     1835                    "MOV: %*sSyncing samples (keyframes) table! (%d entries) (ver:%d,flags:%d)\n", level, "",
     1836                    entries, ver, flags);
     1837            trak->keyframes_size = entries;
     1838            trak->keyframes = calloc(entries, sizeof(unsigned int));
     1839            for (i = 0; i < entries; i++)
     1840                trak->keyframes[i] = stream_read_dword(demuxer->stream) - 1;
     1841            break;
     1842        }
     1843        case MOV_FOURCC('m','d','i','a'): {
     1844            dprintf( "MOV: %*sMedia stream!\n", level, "");
     1845            lschunks(demuxer, level + 1, pos + len, trak);
     1846            break;
     1847        }
     1848        case MOV_FOURCC('m','i','n','f'): {
     1849            dprintf( "MOV: %*sMedia info!\n", level, "");
     1850            lschunks(demuxer, level + 1 ,pos + len, trak);
     1851            break;
     1852        }
     1853        case MOV_FOURCC('s','t','b','l'): {
     1854            dprintf( "MOV: %*sSample info!\n", level, "");
     1855            lschunks(demuxer, level + 1, pos + len, trak);
     1856            break;
     1857        }
     1858        case MOV_FOURCC('e','d','t','s'): {
     1859            dprintf( "MOV: %*sEdit atom!\n", level, "");
     1860            lschunks(demuxer, level + 1, pos + len, trak);
     1861            break;
     1862        }
     1863        case MOV_FOURCC('e','l','s','t'): {
     1864            int temp = stream_read_dword(demuxer->stream);
     1865            int entries = stream_read_dword(demuxer->stream);
     1866            int ver = (temp << 24);
     1867            int flags = (temp << 16) | (temp << 8) | temp;
     1868            int i;
     1869            dprintf(
     1870                    "MOV: %*sEdit list table (%d entries) (ver:%d,flags:%d)\n", level, "",
     1871                    entries, ver, flags);
     1872#if 1
     1873            trak->editlist_size = entries;
     1874            trak->editlist = calloc(trak->editlist_size, sizeof(mov_editlist_t));
     1875            for (i = 0; i < entries; i++) {
     1876                int dur = stream_read_dword(demuxer->stream);
     1877                int mt = stream_read_dword(demuxer->stream);
     1878                int mr = stream_read_dword(demuxer->stream); // 16.16fp
     1879                trak->editlist[i].dur = dur;
     1880                trak->editlist[i].pos = mt;
     1881                trak->editlist[i].speed = mr;
     1882                dprintf(
     1883                        "MOV: %*s  entry#%d: duration: %d  start time: %d  speed: %3.1fx\n", level, "",
     1884                        i, dur, mt, (float)mr/65536.0f);
     1885            }
     1886#endif
     1887            break;
     1888        }
     1889        case MOV_FOURCC('c','o','d','e'): {
     1890            /* XXX: Implement atom 'code' for FLASH support */
     1891            break;
     1892        }
     1893        default:
     1894            id = be2me_32(id);
     1895            dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
     1896            break;
     1897        }//switch(id)
     1898        return 0;
     1899    }
     1900
     1901    static demuxer_t* mov_read_header(demuxer_t* demuxer){
     1902        mov_priv_t* priv=demuxer->priv;
     1903        int t_no;
     1904        int best_a_id=-1, best_a_len=0;
     1905        int best_v_id=-1, best_v_len=0;
     1906
     1907        dprintf( "mov_read_header!\n");
     1908
     1909        // Parse header:
     1910        stream_reset(demuxer->stream);
     1911        if(!stream_seek(demuxer->stream,priv->moov_start))
     1912        {
     1913            dprintf("MOV: Cannot seek to the beginning of the Movie header (0x%"PRIx64")\n",
     1914                    (int64_t)priv->moov_start);
     1915            return 0;
     1916        }
     1917        lschunks(demuxer, 0, priv->moov_end, NULL);
     1918        // just in case we have hit eof while parsing...
     1919        demuxer->stream->eof = 0;
     1920        //    dprintf( "--------------\n");
     1921
     1922        // find the best (longest) streams:
     1923        for(t_no=0;t_no<priv->track_db;t_no++){
     1924            mov_track_t* trak=priv->tracks[t_no];
     1925            int len=(trak->samplesize) ? trak->chunks_size : trak->samples_size;
     1926            if(demuxer->a_streams[t_no]){ // need audio
     1927                if(len>best_a_len){     best_a_len=len; best_a_id=t_no; }
     1928            }
     1929            if(demuxer->v_streams[t_no]){ // need video
     1930                if(len>best_v_len){     best_v_len=len; best_v_id=t_no; }
     1931            }
     1932        }
     1933        dprintf( "MOV: longest streams: A: #%d (%d samples)  V: #%d (%d samples)\n",
     1934                best_a_id,best_a_len,best_v_id,best_v_len);
     1935        if(demuxer->audio->id==-1 && best_a_id>=0) demuxer->audio->id=best_a_id;
     1936        if(demuxer->video->id==-1 && best_v_id>=0) demuxer->video->id=best_v_id;
     1937
     1938        // setup sh pointers:
     1939        if(demuxer->audio->id>=0){
     1940            sh_audio_t* sh=demuxer->a_streams[demuxer->audio->id];
     1941            if(sh){
     1942                demuxer->audio->sh=sh; sh->ds=demuxer->audio;
     1943            } else {
     1944                dprintf( "MOV: selected audio stream (%d) does not exists\n",demuxer->audio->id);
     1945                demuxer->audio->id=-2;
     1946            }
     1947        }
     1948        if(demuxer->video->id>=0){
     1949            sh_video_t* sh=demuxer->v_streams[demuxer->video->id];
     1950            if(sh){
     1951                demuxer->video->sh=sh; sh->ds=demuxer->video;
     1952            } else {
     1953                dprintf( "MOV: selected video stream (%d) does not exists\n",demuxer->video->id);
     1954                demuxer->video->id=-2;
     1955            }
     1956        }
     1957
     1958        if(demuxer->sub->id>=0){
     1959            sh_sub_t* sh=demuxer->s_streams[demuxer->sub->id];
     1960            if(sh){
     1961                demuxer->sub->sh=sh;
     1962            } else {
     1963                dprintf("MOV: selected video stream (%d) does not exists\n",demuxer->video->id);
     1964                demuxer->sub->id=-2;
     1965            }
     1966        }
     1967        if(demuxer->video->id<0 && demuxer->audio->id<0) {
     1968            /* No AV streams found. Try to find an MPEG stream. */
     1969            for(t_no=0;t_no<priv->track_db;t_no++){
     1970                mov_track_t* trak=priv->tracks[t_no];
     1971                if(trak->media_handler == MOV_FOURCC('M','P','E','G')) {
     1972                    stream_t *s;
     1973                    demuxer_t *od;
     1974
     1975                    demuxer->video->id = t_no;
     1976                    s = new_ds_stream(demuxer->video);
     1977                    od = demux_open(s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL);
     1978                    if(od) return new_demuxers_demuxer(od, od, od);
     1979                    demuxer->video->id = -2;        //new linked demuxer couldn't be allocated
    12911980                    break;
    12921981                }
    1293                 case MOV_TRAK_GENERIC:
    1294                     dprintf( "Generic track - not completely understood! (id: %d)\n",
    1295                             trak->id);
    1296                     /* XXX: Also this contains the FLASH data */
     1982            }
     1983        }
    12971984
    12981985#if 0
     1986        if( mp_msg_test(MSGL_DBG3) ){
     1987            for(t_no=0;t_no<priv->track_db;t_no++){
     1988                mov_track_t* trak=priv->tracks[t_no];
     1989                if(trak->type==MOV_TRAK_GENERIC){
     1990                    int i;
     1991                    int fd;
     1992                    char name[20];
     1993                    dprintf( "MOV: Track #%d: Extracting %d data chunks to files\n",t_no,trak->samples_size);
     1994                    for (i=0; i<trak->samples_size; i++)
    12991995                    {
    1300                         int pos = stream_tell(demuxer->stream);
    1301                         int i;
    1302                         int fd;
    1303                         char name[20];
    1304 
    1305                         for (i=0; i<trak->samples_size; i++)
     1996                        int len=trak->samples[i].size;
     1997                        char buf[len];
     1998                        stream_seek(demuxer->stream, trak->samples[i].pos);
     1999                        snprintf(name, 20, "t%02d-s%03d.%s", t_no,i,
     2000                                 (trak->media_handler==MOV_FOURCC('f','l','s','h')) ?
     2001                                 "swf":"dump");
     2002                        fd = open(name, O_CREAT|O_WRONLY);
     2003                        //                  { int j;
     2004                        //                      for(j=0;j<trak->stdata_len-3; j++)
     2005                        //                          printf("stdata[%d]=0x%X ize=0x%X\n",j,char2int(trak->stdata,j),MOV_FOURCC('z','l','i','b'));
     2006                        //                  }
     2007                        if( //trak->media_handler==MOV_FOURCC('s','p','r','t') &&
     2008                           trak->stdata_len>=16 &&
     2009                           char2int(trak->stdata,12)==MOV_FOURCC('z','l','i','b')
     2010                          ){
     2011                            int newlen=stream_read_dword(demuxer->stream);
     2012#ifdef HAVE_ZLIB
     2013                            // unzip:
     2014                            z_stream zstrm;
     2015                            int zret;
     2016                            char buf2[newlen];
     2017
     2018                            len-=4;
     2019                            stream_read(demuxer->stream, buf, len);
     2020
     2021                            zstrm.zalloc          = (alloc_func)0;
     2022                            zstrm.zfree           = (free_func)0;
     2023                            zstrm.opaque          = (voidpf)0;
     2024                            zstrm.next_in         = buf;
     2025                            zstrm.avail_in        = len;
     2026                            zstrm.next_out        = buf2;
     2027                            zstrm.avail_out       = newlen;
     2028
     2029                            zret = inflateInit(&zstrm);
     2030                            zret = inflate(&zstrm, Z_NO_FLUSH);
     2031                            if(newlen != zstrm.total_out)
     2032                                dprintf( "Warning! unzipped frame size differs hdr: %d  zlib: %ld\n",newlen,zstrm.total_out);
     2033
     2034                            write(fd, buf2, newlen);
     2035                        } else {
     2036#else
     2037                            len-=4;
     2038                            dprintf( "******* ZLIB COMPRESSED SAMPLE!!!!! (%d->%d bytes) *******\n",len,newlen);
     2039                        }
    13062040                        {
    1307                             char buf[trak->samples[i].size];
    1308                             stream_seek(demuxer->stream, trak->samples[i].pos);
    1309                             snprintf((char *)&name[0], 20, "samp%d", i);
    1310                             fd = open((char *)&name[0], O_CREAT|O_WRONLY);
    1311                             stream_read(demuxer->stream, &buf[0], trak->samples[i].size);
    1312                             write(fd, &buf[0], trak->samples[i].size);
    1313                             close(fd);
     2041#endif
     2042                            stream_read(demuxer->stream, buf, len);
     2043                            write(fd, buf, len);
    13142044                        }
    1315                         for (i=0; i<trak->chunks_size; i++)
    1316                         {
    1317                             char buf[trak->length];
    1318                             stream_seek(demuxer->stream, trak->chunks[i].pos);
    1319                             snprintf((char *)&name[0], 20, "chunk%d", i);
    1320                             fd = open((char *)&name[0], O_CREAT|O_WRONLY);
    1321                             stream_read(demuxer->stream, &buf[0], trak->length);
    1322                             write(fd, &buf[0], trak->length);
    1323                             close(fd);
    1324                         }
    1325                         if (trak->samplesize > 0)
    1326                         {
    1327                             char *buf;
    1328 
    1329                             buf = malloc(trak->samplesize);
    1330                             stream_seek(demuxer->stream, trak->chunks[0].pos);
    1331                             snprintf((char *)&name[0], 20, "trak%d", trak->id);
    1332                             fd = open((char *)&name[0], O_CREAT|O_WRONLY);
    1333                             stream_read(demuxer->stream, buf, trak->samplesize);
    1334                             write(fd, buf, trak->samplesize);
    1335                             close(fd);
    1336                         }
    1337                         stream_seek(demuxer->stream, pos);
     2045                        close(fd);
    13382046                    }
     2047                }
     2048            }
     2049        }
     2050        demuxer->stream->eof = 0;
    13392051#endif
    1340                     break;
    1341                 default:
    1342                     dprintf( "Unknown track type found (type: %d)\n", trak->type);
    1343                     break;
     2052        return demuxer;
     2053    }
     2054
     2055    /**
     2056     * \brief return the mov track that belongs to a demuxer stream
     2057     * \param ds the demuxer stream, may be NULL
     2058     * \return the mov track info structure belonging to the stream,
     2059     *          NULL if not found
     2060     */
     2061    static mov_track_t *stream_track(mov_priv_t *priv, demux_stream_t *ds) {
     2062        if (ds && (ds->id >= 0) && (ds->id < priv->track_db))
     2063            return priv->tracks[ds->id];
     2064        return NULL;
     2065    }
     2066
     2067    // return value:
     2068    //     0 = EOF or no stream found
     2069    //     1 = successfully read a packet
     2070    static int demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){
     2071        mov_priv_t* priv=demuxer->priv;
     2072        mov_track_t* trak=NULL;
     2073        float pts;
     2074        int x;
     2075        off_t pos;
     2076
     2077        if (ds->eof) return 0;
     2078        trak = stream_track(priv, ds);
     2079        if (!trak) return 0;
     2080
     2081        if(trak->samplesize){
     2082            // read chunk:
     2083            if(trak->pos>=trak->chunks_size) return 0; // EOF
     2084            stream_seek(demuxer->stream,trak->chunks[trak->pos].pos);
     2085            pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale;
     2086            if(trak->samplesize!=1)
     2087            {
     2088                dprintf( "WARNING! Samplesize(%d) != 1\n",
     2089                        trak->samplesize);
     2090                if((trak->fourcc != MOV_FOURCC('t','w','o','s')) && (trak->fourcc != MOV_FOURCC('s','o','w','t')))
     2091                    x=trak->chunks[trak->pos].size*trak->samplesize;
     2092                else
     2093                    x=trak->chunks[trak->pos].size;
     2094            }
     2095            x=trak->chunks[trak->pos].size;
     2096            //    printf("X = %d\n", x);
     2097            /* the following stuff is audio related */
     2098            if (trak->type == MOV_TRAK_AUDIO){
     2099                if(trak->stdata_len>=44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){
     2100                    // stsd version 1 - we have audio compression ratio info:
     2101                    x/=char2int(trak->stdata,28); // samples/packet
     2102                    //  x*=char2int(trak->stdata,32); // bytes/packet
     2103                    x*=char2int(trak->stdata,36); // bytes/frame
     2104                } else {
     2105                    if(ds->ss_div && ds->ss_mul){
     2106                        // workaround for buggy files like 7up-high-traffic-areas.mov,
     2107                        // with missing stsd v1 header containing compression rate
     2108                        x/=ds->ss_div; x*=ds->ss_mul; // compression ratio fix  ! HACK !
     2109                    } else {
     2110                        x*=trak->nchannels;
     2111                        x*=trak->samplebytes;
     2112                    }
    13442113                }
    1345                 dprintf( "--------------\n");
    1346                 priv->track_db++;
    1347                 trak=NULL;
    1348                 break;
    1349             }
    1350 #ifndef HAVE_ZLIB
    1351             case MOV_FOURCC('c','m','o','v'): {
    1352                 dprintf("MOV: got compressed header but have no zlib\n");
    1353                 return;
    1354             }
    1355 #else
    1356             case MOV_FOURCC('m','o','o','v'):
    1357             case MOV_FOURCC('c','m','o','v'): {
    1358                 //          dprintf(MSGTR_MOVcomprhdr);
    1359                 lschunks(demuxer,level+1,pos+len,NULL);
    1360                 break;
    1361             }
    1362             case MOV_FOURCC('d','c','o','m'): {
    1363                 //          int temp=stream_read_dword(demuxer->stream);
    1364                 unsigned int algo=be2me_32(stream_read_dword(demuxer->stream));
    1365                 dprintf( "Compressed header uses %.4s algo!\n",(char *)&algo);
    1366                 break;
    1367             }
    1368             case MOV_FOURCC('c','m','v','d'): {
    1369                 //          int temp=stream_read_dword(demuxer->stream);
    1370                 unsigned int moov_sz=stream_read_dword(demuxer->stream);
    1371                 unsigned int cmov_sz=len-4;
    1372                 unsigned char* cmov_buf;
    1373                 unsigned char* moov_buf;
    1374                 int zret;
    1375                 z_stream zstrm;
    1376                 stream_t* backup;
    1377 
    1378                 if (moov_sz > 0xffffffff - 16) {
    1379                     dprintf("Invalid cmvd atom size %d\n", moov_sz);
    1380                     break;
     2114                dprintf( "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts);
     2115            } /* MOV_TRAK_AUDIO */
     2116            pos=trak->chunks[trak->pos].pos;
     2117        } else {
     2118            int frame=trak->pos;
     2119            // editlist support:
     2120            if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){
     2121                // find the right editlist entry:
     2122                if(frame<trak->editlist[trak->editlist_pos].start_frame)
     2123                    trak->editlist_pos=0;
     2124                while(trak->editlist_pos<trak->editlist_size-1 &&
     2125                      frame>=trak->editlist[trak->editlist_pos+1].start_frame)
     2126                    ++trak->editlist_pos;
     2127                if(frame>=trak->editlist[trak->editlist_pos].start_frame+
     2128                   trak->editlist[trak->editlist_pos].frames) return 0; // EOF
     2129                // calc real frame index:
     2130                frame-=trak->editlist[trak->editlist_pos].start_frame;
     2131                frame+=trak->editlist[trak->editlist_pos].start_sample;
     2132                // calc pts:
     2133                pts=(float)(trak->samples[frame].pts+
     2134                            trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale;
     2135            } else {
     2136                if(frame>=trak->samples_size) return 0; // EOF
     2137                pts=(float)trak->samples[frame].pts/(float)trak->timescale;
     2138            }
     2139            // read sample:
     2140            stream_seek(demuxer->stream,trak->samples[frame].pos);
     2141            x=trak->samples[frame].size;
     2142            pos=trak->samples[frame].pos;
     2143        }
     2144        if(trak->pos==0 && trak->stream_header_len>0){
     2145            // we have to append the stream header...
     2146            demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len);
     2147            memcpy(dp->buffer,trak->stream_header,trak->stream_header_len);
     2148            stream_read(demuxer->stream,dp->buffer+trak->stream_header_len,x);
     2149            free(trak->stream_header);
     2150            trak->stream_header = NULL;
     2151            trak->stream_header_len = 0;
     2152            dp->pts=pts;
     2153            dp->flags=0;
     2154            dp->pos=pos; // FIXME?
     2155            ds_add_packet(ds,dp);
     2156        } else
     2157            ds_read_packet(ds,demuxer->stream,x,pts,pos,0);
     2158
     2159        ++trak->pos;
     2160        if (demuxer->sub->id >= 0) {
     2161            int samplenr = 0;
     2162            trak = priv->tracks[demuxer->sub->id];
     2163            while (samplenr < trak->samples_size) {
     2164                double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale;
     2165                if (subpts >= pts) break;
     2166                samplenr++;
     2167            }
     2168            samplenr--;
     2169            if (samplenr < 0)
     2170                vo_sub = NULL;
     2171            else if (samplenr != priv->current_sub) {
     2172                sh_sub_t *sh = demuxer->sub->sh;
     2173                off_t pos = trak->samples[samplenr].pos;
     2174                int len = trak->samples[samplenr].size;
     2175                double subpts = (double)trak->samples[samplenr].pts / (double)trak->timescale;
     2176                stream_seek(demuxer->stream, pos);
     2177                if (sh->type == 'v')
     2178                    ds_read_packet(demuxer->sub, demuxer->stream, len, subpts, pos, 0);
     2179                else {
     2180                    int i;
     2181                    char *line = priv->subtext;
     2182                    stream_skip(demuxer->stream, 2); // size
     2183                    len -= 2;
     2184                    if (len < 0) len = 0;
     2185                    if (len > MOV_MAX_SUBLEN) len = MOV_MAX_SUBLEN;
     2186                    stream_read(demuxer->stream, priv->subtext, len);
     2187                    priv->subtext[len] = 0;
     2188                    priv->subs.lines = 1;
     2189                    priv->subs.text[0] = &priv->subtext;
     2190                    while ((line = strchr(line, '\n'))) {
     2191                        *line++ = 0;
     2192                        priv->subs.text[priv->subs.lines] = line;
     2193                        priv->subs.lines++;
     2194                    }
     2195                    vo_sub = &priv->subs;
    13812196                }
    1382                 cmov_buf=malloc(cmov_sz);
    1383                 moov_buf=malloc(moov_sz+16);
    1384                 dprintf( "Compressed header size: %d / %d\n",cmov_sz,moov_sz);
    1385 
    1386                 stream_read(demuxer->stream,cmov_buf,cmov_sz);
    1387 
    1388                 zstrm.zalloc          = (alloc_func)0;
    1389                 zstrm.zfree           = (free_func)0;
    1390                 zstrm.opaque          = (voidpf)0;
    1391                 zstrm.next_in         = cmov_buf;
    1392                 zstrm.avail_in        = cmov_sz;
    1393                 zstrm.next_out        = moov_buf;
    1394                 zstrm.avail_out       = moov_sz;
    1395 
    1396                 zret = inflateInit(&zstrm);
    1397                 if (zret != Z_OK)
    1398                 { dprintf( "QT cmov: inflateInit err %d\n",zret);
    1399                     return;
     2197                priv->current_sub = samplenr;
     2198            }
     2199            vo_osd_changed (OSDTYPE_SUBTITLE);
     2200        }
     2201
     2202        return 1;
     2203
     2204    }
     2205
     2206    static float mov_seek_track(mov_track_t* trak,float pts,int flags){
     2207
     2208        //    printf("MOV track seek called  %5.3f  \n",pts);
     2209        if(flags&2) pts*=trak->length; else pts*=(float)trak->timescale;
     2210
     2211        if(trak->samplesize){
     2212            int sample=pts/trak->duration;
     2213            //    printf("MOV track seek - chunk: %d  (pts: %5.3f  dur=%d)  \n",sample,pts,trak->duration);
     2214            if(!(flags&1)) sample+=trak->chunks[trak->pos].sample; // relative
     2215            trak->pos=0;
     2216            while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos;
     2217            if (trak->pos == trak->chunks_size) return -1;
     2218            pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale;
     2219        } else {
     2220            unsigned int ipts;
     2221            if(!(flags&1)) pts+=trak->samples[trak->pos].pts;
     2222            if(pts<0) pts=0;
     2223            ipts=pts;
     2224            //printf("MOV track seek - sample: %d  \n",ipts);
     2225            for(trak->pos=0;trak->pos<trak->samples_size;++trak->pos){
     2226                if(trak->samples[trak->pos].pts>=ipts) break; // found it!
     2227            }
     2228            if (trak->pos == trak->samples_size) return -1;
     2229            if(trak->keyframes_size){
     2230                // find nearest keyframe
     2231                int i;
     2232                for(i=0;i<trak->keyframes_size;i++){
     2233                    if(trak->keyframes[i]>=trak->pos) break;
    14002234                }
    1401                 zret = inflate(&zstrm, Z_NO_FLUSH);
    1402                 if ((zret != Z_OK) && (zret != Z_STREAM_END))
    1403                 { dprintf( "QT cmov inflate: ERR %d\n",zret);
    1404                     return;
    1405                 }
    1406 #if 0
    1407                 else {
    1408                     FILE *DecOut;
    1409                     DecOut = fopen("Out.bin", "w");
    1410                     fwrite(moov_buf, 1, moov_sz, DecOut);
    1411                     fclose(DecOut);
    1412                 }
    1413 #endif
    1414                 if(moov_sz != zstrm.total_out)
    1415                     dprintf( "Warning! moov size differs cmov: %d  zlib: %ld\n",moov_sz,zstrm.total_out);
    1416                 zret = inflateEnd(&zstrm);
    1417 
    1418                 backup=demuxer->stream;
    1419                 demuxer->stream=new_memory_stream(moov_buf,moov_sz);
    1420                 stream_skip(demuxer->stream,8);
    1421                 lschunks(demuxer,level+1,moov_sz,NULL); // parse uncompr. 'moov'
    1422                 //free_stream(demuxer->stream);
    1423                 demuxer->stream=backup;
    1424                 free(cmov_buf);
    1425                 free(moov_buf);
    1426                 break;
    1427             }
    1428 #endif
    1429             case MOV_FOURCC('u','d','t','a'):
    1430                 {
    1431                     unsigned int udta_id;
    1432                     off_t udta_len;
    1433                     off_t udta_size = len;
    1434 
    1435                     dprintf( "mov: user data record found\n");
    1436                     dprintf( "Quicktime Clip Info:\n");
    1437 
    1438                     while((len > 8) && (udta_size > 8))
    1439                     {
    1440                         udta_len = stream_read_dword(demuxer->stream);
    1441                         udta_id = stream_read_dword(demuxer->stream);
    1442                         udta_size -= 8;
    1443                         dprintf( "udta_id: %.4s (len: %"PRId64")\n", (char *)&udta_id, (int64_t)udta_len);
    1444                         switch (udta_id)
    1445                         {
    1446                         case MOV_FOURCC(0xa9,'c','p','y'):
    1447                         case MOV_FOURCC(0xa9,'d','a','y'):
    1448                         case MOV_FOURCC(0xa9,'d','i','r'):
    1449                             /* 0xa9,'e','d','1' - '9' : edit timestamps */
    1450                         case MOV_FOURCC(0xa9,'f','m','t'):
    1451                         case MOV_FOURCC(0xa9,'i','n','f'):
    1452                         case MOV_FOURCC(0xa9,'p','r','d'):
    1453                         case MOV_FOURCC(0xa9,'p','r','f'):
    1454                         case MOV_FOURCC(0xa9,'r','e','q'):
    1455                         case MOV_FOURCC(0xa9,'s','r','c'):
    1456                         case MOV_FOURCC('n','a','m','e'):
    1457                         case MOV_FOURCC(0xa9,'n','a','m'):
    1458                         case MOV_FOURCC(0xa9,'A','R','T'):
    1459                         case MOV_FOURCC(0xa9,'c','m','t'):
    1460                         case MOV_FOURCC(0xa9,'a','u','t'):
    1461                         case MOV_FOURCC(0xa9,'s','w','r'):
    1462                             {
    1463                                 off_t text_len = stream_read_word(demuxer->stream);
    1464                                 char text[text_len+2+1];
    1465                                 stream_read(demuxer->stream, (char *)&text, text_len+2);
    1466                                 text[text_len+2] = 0x0;
    1467                                 switch(udta_id)
    1468                                 {
    1469                                 case MOV_FOURCC(0xa9,'a','u','t'):
    1470                                     demux_info_add(demuxer, "author", &text[2]);
    1471                                     dprintf( " Author: %s\n", &text[2]);
    1472                                     break;
    1473                                 case MOV_FOURCC(0xa9,'c','p','y'):
    1474                                     demux_info_add(demuxer, "copyright", &text[2]);
    1475                                     dprintf( " Copyright: %s\n", &text[2]);
    1476                                     break;
    1477                                 case MOV_FOURCC(0xa9,'i','n','f'):
    1478                                     dprintf( " Info: %s\n", &text[2]);
    1479                                     break;
    1480                                 case MOV_FOURCC('n','a','m','e'):
    1481                                 case MOV_FOURCC(0xa9,'n','a','m'):
    1482                                     demux_info_add(demuxer, "name", &text[2]);
    1483                                     dprintf( " Name: %s\n", &text[2]);
    1484                                     break;
    1485                                 case MOV_FOURCC(0xa9,'A','R','T'):
    1486                                     dprintf( " Artist: %s\n", &text[2]);
    1487                                     break;
    1488                                 case MOV_FOURCC(0xa9,'d','i','r'):
    1489                                     dprintf( " Director: %s\n", &text[2]);
    1490                                     break;
    1491                                 case MOV_FOURCC(0xa9,'c','m','t'):
    1492                                     demux_info_add(demuxer, "comments", &text[2]);
    1493                                     dprintf( " Comment: %s\n", &text[2]);
    1494                                     break;
    1495                                 case MOV_FOURCC(0xa9,'r','e','q'):
    1496                                     dprintf( " Requirements: %s\n", &text[2]);
    1497                                     break;
    1498                                 case MOV_FOURCC(0xa9,'s','w','r'):
    1499                                     demux_info_add(demuxer, "encoder", &text[2]);
    1500                                     dprintf( " Software: %s\n", &text[2]);
    1501                                     break;
    1502                                 case MOV_FOURCC(0xa9,'d','a','y'):
    1503                                     dprintf( " Creation timestamp: %s\n", &text[2]);
    1504                                     break;
    1505                                 case MOV_FOURCC(0xa9,'f','m','t'):
    1506                                     dprintf( " Format: %s\n", &text[2]);
    1507                                     break;
    1508                                 case MOV_FOURCC(0xa9,'p','r','d'):
    1509                                     dprintf( " Producer: %s\n", &text[2]);
    1510                                     break;
    1511                                 case MOV_FOURCC(0xa9,'p','r','f'):
    1512                                     dprintf( " Performer(s): %s\n", &text[2]);
    1513                                     break;
    1514                                 case MOV_FOURCC(0xa9,'s','r','c'):
    1515                                     dprintf( " Source providers: %s\n", &text[2]);
    1516                                     break;
    1517                                 }
    1518                                 udta_size -= 4+text_len;
    1519                                 break;
    1520                             }
    1521                             /* some other shits:    WLOC - window location,
    1522                              LOOP - looping style,
    1523                              SelO - play only selected frames
    1524                              AllF - play all frames
    1525                              */
    1526                         case MOV_FOURCC('W','L','O','C'):
    1527                         case MOV_FOURCC('L','O','O','P'):
    1528                         case MOV_FOURCC('S','e','l','O'):
    1529                         case MOV_FOURCC('A','l','l','F'):
    1530                         default:
    1531                             {
    1532                                 if( udta_len>udta_size)
    1533                                     udta_len=udta_size;
    1534                                 {
    1535                                     char dump[udta_len-4];
    1536                                     stream_read(demuxer->stream, (char *)&dump, udta_len-4-4);
    1537                                     udta_size -= udta_len;
    1538                                 }
    1539                             }
    1540                         }
    1541                     }
    1542                     break;
    1543                 } /* eof udta */
    1544             default:
    1545                 id = be2me_32(id);
    1546                 dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
    1547             } /* endof switch */
    1548         } /* endof else */
    1549 
    1550         pos+=len+8;
    1551         if(pos>=endpos) break;
    1552         if(!stream_seek(demuxer->stream,pos)) break;
     2235                if (i == trak->keyframes_size) return -1;
     2236                if(i>0 && (trak->keyframes[i]-trak->pos) > (trak->pos-trak->keyframes[i-1]))
     2237                    --i;
     2238                trak->pos=trak->keyframes[i];
     2239                //      printf("nearest keyframe: %d  \n",trak->pos);
     2240            }
     2241            pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale;
     2242        }
     2243
     2244        //    printf("MOV track seek done:  %5.3f  \n",pts);
     2245
     2246        return pts;
    15532247    }
    1554 }
    1555 
    1556 static int lschunks_intrak(demuxer_t* demuxer, int level, unsigned int id,
    1557                            off_t pos, off_t len, mov_track_t* trak)
    1558 {
    1559   switch(id) {
    1560     case MOV_FOURCC('m','d','a','t'): {
    1561       dprintf("Hmm, strange MOV, parsing mdat in lschunks?\n");
    1562       return -1;
     2248
     2249    static void demux_seek_mov(demuxer_t *demuxer,float pts,int flags){
     2250        mov_priv_t* priv=demuxer->priv;
     2251        demux_stream_t* ds;
     2252        mov_track_t* trak;
     2253
     2254        //    printf("MOV seek called  %5.3f  flag=%d  \n",pts,flags);
     2255
     2256        ds=demuxer->video;
     2257        trak = stream_track(priv, ds);
     2258        if (trak) {
     2259            //if(flags&2) pts*=(float)trak->length/(float)trak->timescale;
     2260            //if(!(flags&1)) pts+=ds->pts;
     2261            ds->pts=mov_seek_track(trak,pts,flags);
     2262            if (ds->pts < 0) ds->eof = 1;
     2263            else pts = ds->pts;
     2264            flags=1; // absolute seconds
     2265        }
     2266
     2267        ds=demuxer->audio;
     2268        trak = stream_track(priv, ds);
     2269        if (trak) {
     2270            //if(flags&2) pts*=(float)trak->length/(float)trak->timescale;
     2271            //if(!(flags&1)) pts+=ds->pts;
     2272            ds->pts=mov_seek_track(trak,pts,flags);
     2273            if (ds->pts < 0) ds->eof = 1;
     2274            if (demuxer->video->id < 0)
     2275                ((sh_audio_t*)ds->sh)->delay = ds->pts;
     2276        }
     2277
    15632278    }
    1564     case MOV_FOURCC('f','r','e','e'):
    1565     case MOV_FOURCC('u','d','t','a'):
    1566       /* here not supported :p */
    1567       break;
    1568     case MOV_FOURCC('t','k','h','d'): {
    1569       dprintf("MOV: %*sTrack header!\n", level, "");
    1570       // read codec data
    1571       trak->tkdata_len = len;
    1572       trak->tkdata = malloc(trak->tkdata_len);
    1573       stream_read(demuxer->stream, trak->tkdata, trak->tkdata_len);
    1574 /*
    1575 0  1 Version
    1576 1  3 Flags
    1577 4  4 Creation time
    1578 8  4 Modification time
    1579 12 4 Track ID
    1580 16 4 Reserved
    1581 20 4 Duration
    1582 24 8 Reserved
    1583 32 2 Layer
    1584 34 2 Alternate group
    1585 36 2 Volume
    1586 38 2 Reserved
    1587 40 36 Matrix structure
    1588 76 4 Track width
    1589 80 4 Track height
    1590 */
    1591       dprintf(
    1592              "tkhd len=%d ver=%d flags=0x%X id=%d dur=%d lay=%d vol=%d\n",
    1593               trak->tkdata_len, trak->tkdata[0], trak->tkdata[1],
    1594               char2int(trak->tkdata, 12), // id
    1595               char2int(trak->tkdata, 20), // duration
    1596               char2short(trak->tkdata, 32), // layer
    1597               char2short(trak->tkdata, 36)); // volume
    1598       break;
     2279
     2280    static int demux_mov_control(demuxer_t *demuxer, int cmd, void *arg){
     2281        mov_track_t* track;
     2282
     2283        // try the video track
     2284        track = stream_track(demuxer->priv, demuxer->video);
     2285        if (!track || !track->length)
     2286            // otherwise try to get the info from the audio track
     2287            track = stream_track(demuxer->priv, demuxer->audio);
     2288
     2289        if (!track || !track->length)
     2290            return DEMUXER_CTRL_DONTKNOW;
     2291
     2292        switch(cmd) {
     2293        case DEMUXER_CTRL_GET_TIME_LENGTH:
     2294            if (!track->timescale)
     2295                return DEMUXER_CTRL_DONTKNOW;
     2296            *((double *)arg) = (double)track->length / track->timescale;
     2297            return DEMUXER_CTRL_OK;
     2298
     2299        case DEMUXER_CTRL_GET_PERCENT_POS:
     2300            {
     2301                off_t pos = track->pos;
     2302                if (track->durmap_size >= 1)
     2303                    pos *= track->durmap[0].dur;
     2304                *((int *)arg) = (int)(100 * pos / track->length);
     2305                return DEMUXER_CTRL_OK;
     2306            }
     2307        }
     2308        return DEMUXER_CTRL_NOTIMPL;
    15992309    }
    1600     case MOV_FOURCC('m','d','h','d'): {
    1601         dprintf( "MOV: %*sMedia header!\n", level, "");
    1602         int version = stream_read_char(demuxer->stream);
    1603         stream_skip(demuxer->stream, (version == 1) ? 19 : 11);
    1604         // read timescale
    1605         trak->timescale = stream_read_dword(demuxer->stream);
    1606         // read length
    1607         if (version == 1)
    1608             trak->length = stream_read_qword(demuxer->stream);
    1609         else
    1610             trak->length = stream_read_dword(demuxer->stream);
    1611       break;
    1612     }
    1613     case MOV_FOURCC('h','d','l','r'): {
    1614       unsigned int tmp = stream_read_dword(demuxer->stream);
    1615       unsigned int type = stream_read_dword_le(demuxer->stream);
    1616       unsigned int subtype = stream_read_dword_le(demuxer->stream);
    1617       unsigned int manufact = stream_read_dword_le(demuxer->stream);
    1618       unsigned int comp_flags = stream_read_dword(demuxer->stream);
    1619       unsigned int comp_mask = stream_read_dword(demuxer->stream);
    1620       int len = stream_read_char(demuxer->stream);
    1621       char* str = malloc(len + 1);
    1622       stream_read(demuxer->stream, str, len);
    1623       str[len] = 0;
    1624       dprintf(
    1625              "MOV: %*sHandler header: %.4s/%.4s (%.4s) %s\n", level, "",
    1626              (char *)&type, (char *)&subtype, (char *)&manufact, str);
    1627       free(str);
    1628       switch(bswap_32(type)) {
    1629         case MOV_FOURCC('m','h','l','r'):
    1630           trak->media_handler = bswap_32(subtype);
    1631           break;
    1632         case MOV_FOURCC('d','h','l','r'):
    1633           trak->data_handler = bswap_32(subtype);
    1634           break;
    1635         default:
    1636           dprintf(
    1637                  "MOV: unknown handler class: 0x%X (%.4s)\n",
    1638                  bswap_32(type), (char *)&type);
    1639       }
    1640       break;
    1641     }
    1642     case MOV_FOURCC('v','m','h','d'): {
    1643       dprintf( "MOV: %*sVideo header!\n", level, "");
    1644       trak->type = MOV_TRAK_VIDEO;
    1645       // read video data
    1646       break;
    1647     }
    1648     case MOV_FOURCC('s','m','h','d'): {
    1649       dprintf( "MOV: %*sSound header!\n", level, "");
    1650       trak->type = MOV_TRAK_AUDIO;
    1651       // read audio data
    1652       break;
    1653     }
    1654     case MOV_FOURCC('g','m','h','d'): {
    1655       dprintf( "MOV: %*sGeneric header!\n", level, "");
    1656       trak->type = MOV_TRAK_GENERIC;
    1657       break;
    1658     }
    1659     case MOV_FOURCC('n','m','h','d'): {
    1660       dprintf( "MOV: %*sGeneric header!\n", level, "");
    1661       trak->type = MOV_TRAK_GENERIC;
    1662       break;
    1663     }
    1664     case MOV_FOURCC('s','t','s','d'): {
    1665       int i = stream_read_dword(demuxer->stream); // temp!
    1666       int count = stream_read_dword(demuxer->stream);
    1667       dprintf( "MOV: %*sDescription list! (cnt:%d)\n",
    1668              level, "", count);
    1669       for (i = 0; i < count; i++) {
    1670         off_t pos = stream_tell(demuxer->stream);
    1671         off_t len = stream_read_dword(demuxer->stream);
    1672         unsigned int fourcc = stream_read_dword_le(demuxer->stream);
    1673         /* some files created with Broadcast 2000 (e.g. ilacetest.mov)
    1674            contain raw I420 video but have a yv12 fourcc */
    1675         if (fourcc == mmioFOURCC('y','v','1','2'))
    1676           fourcc = mmioFOURCC('I','4','2','0');
    1677         if (len < 8)
    1678           break; // error
    1679         dprintf(
    1680                "MOV: %*s desc #%d: %.4s  (%"PRId64" bytes)\n", level, "",
    1681                i, (char *)&fourcc, (int64_t)len - 16);
    1682         if (fourcc != trak->fourcc && i)
    1683             dprintf("MOW: warning - different fourcc\n");
    1684 //      if(!i)
    1685         {
    1686           trak->fourcc = fourcc;
    1687           // read type specific (audio/video/time/text etc) header
    1688           // NOTE: trak type is not yet known at this point :(((
    1689           trak->stdata_len = len - 8;
    1690           trak->stdata = malloc(trak->stdata_len);
    1691           stream_read(demuxer->stream, trak->stdata, trak->stdata_len);
    1692         }
    1693         if (!stream_seek(demuxer->stream, pos + len))
    1694           break;
    1695       }
    1696       break;
    1697     }
    1698     case MOV_FOURCC('s','t','t','s'): {
    1699       int temp = stream_read_dword(demuxer->stream);
    1700       int len = stream_read_dword(demuxer->stream);
    1701       int i;
    1702       unsigned int pts = 0;
    1703       dprintf(
    1704              "MOV: %*sSample duration table! (%d blocks)\n", level, "",
    1705               len);
    1706       trak->durmap = calloc(len, sizeof(mov_durmap_t));
    1707       trak->durmap_size = len;
    1708       for (i = 0; i < len; i++) {
    1709         trak->durmap[i].num = stream_read_dword(demuxer->stream);
    1710         trak->durmap[i].dur = stream_read_dword(demuxer->stream);
    1711         pts += trak->durmap[i].num * trak->durmap[i].dur;
    1712       }
    1713       if (trak->length != pts)
    1714         dprintf( "Warning! pts=%d  length=%d\n",
    1715                pts, trak->length);
    1716       break;
    1717     }
    1718     case MOV_FOURCC('s','t','s','c'): {
    1719       int temp = stream_read_dword(demuxer->stream);
    1720       int len = stream_read_dword(demuxer->stream);
    1721       int ver = (temp << 24);
    1722       int flags = (temp << 16) | (temp << 8) | temp;
    1723       int i;
    1724       dprintf(
    1725              "MOV: %*sSample->Chunk mapping table!  (%d blocks) (ver:%d,flags:%d)\n", level, "",
    1726              len, ver, flags);
    1727       // read data:
    1728       trak->chunkmap_size = len;
    1729       trak->chunkmap = calloc(len, sizeof(mov_chunkmap_t));
    1730       for (i = 0; i < len; i++) {
    1731         trak->chunkmap[i].first = stream_read_dword(demuxer->stream) - 1;
    1732         trak->chunkmap[i].spc = stream_read_dword(demuxer->stream);
    1733         trak->chunkmap[i].sdid = stream_read_dword(demuxer->stream);
    1734       }
    1735       break;
    1736     }
    1737     case MOV_FOURCC('s','t','s','z'): {
    1738       int temp = stream_read_dword(demuxer->stream);
    1739       int ss=stream_read_dword(demuxer->stream);
    1740       int ver = (temp << 24);
    1741       int flags = (temp << 16) | (temp << 8) | temp;
    1742       int entries = stream_read_dword(demuxer->stream);
    1743       int i;
    1744       dprintf(
    1745              "MOV: %*sSample size table! (entries=%d ss=%d) (ver:%d,flags:%d)\n", level, "",
    1746              entries, ss, ver, flags);
    1747       trak->samplesize = ss;
    1748       if (!ss) {
    1749           // variable samplesize
    1750           trak->samples = realloc_struct(trak->samples, entries, sizeof(mov_sample_t));
    1751           trak->samples_size = entries;
    1752           for (i = 0; i < entries; i++)
    1753               trak->samples[i].size = stream_read_dword(demuxer->stream);
    1754       }
    1755       break;
    1756     }
    1757     case MOV_FOURCC('s','t','c','o'): {
    1758       int temp = stream_read_dword(demuxer->stream);
    1759       int len = stream_read_dword(demuxer->stream);
    1760       int i;
    1761       dprintf(
    1762              "MOV: %*sChunk offset table! (%d chunks)\n", level, "",
    1763              len);
    1764       // extend array if needed:
    1765       if (len > trak->chunks_size) {
    1766           trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t));
    1767           trak->chunks_size = len;
    1768       }
    1769       // read elements:
    1770       for(i = 0; i < len; i++)
    1771         trak->chunks[i].pos = stream_read_dword(demuxer->stream);
    1772       break;
    1773     }
    1774     case MOV_FOURCC('c','o','6','4'): {
    1775       int temp = stream_read_dword(demuxer->stream);
    1776       int len = stream_read_dword(demuxer->stream);
    1777       int i;
    1778       dprintf(
    1779              "MOV: %*s64bit chunk offset table! (%d chunks)\n", level, "",
    1780              len);
    1781       // extend array if needed:
    1782       if (len > trak->chunks_size) {
    1783           trak->chunks = realloc_struct(trak->chunks, len, sizeof(mov_chunk_t));
    1784           trak->chunks_size = len;
    1785       }
    1786       // read elements:
    1787       for (i = 0; i < len; i++) {
    1788 #ifndef _LARGEFILE_SOURCE
    1789         if (stream_read_dword(demuxer->stream) != 0)
    1790           dprintf( "Chunk %d has got 64bit address, but you've MPlayer compiled without LARGEFILE support!\n", i);
    1791         trak->chunks[i].pos = stream_read_dword(demuxer->stream);
    1792 #else
    1793         trak->chunks[i].pos = stream_read_qword(demuxer->stream);
    1794 #endif
    1795       }
    1796       break;
    1797     }
    1798     case MOV_FOURCC('s','t','s','s'): {
    1799       int temp = stream_read_dword(demuxer->stream);
    1800       int entries = stream_read_dword(demuxer->stream);
    1801       int ver = (temp << 24);
    1802       int flags = (temp << 16) | (temp<<8) | temp;
    1803       int i;
    1804       dprintf(
    1805              "MOV: %*sSyncing samples (keyframes) table! (%d entries) (ver:%d,flags:%d)\n", level, "",
    1806              entries, ver, flags);
    1807       trak->keyframes_size = entries;
    1808       trak->keyframes = calloc(entries, sizeof(unsigned int));
    1809       for (i = 0; i < entries; i++)
    1810           trak->keyframes[i] = stream_read_dword(demuxer->stream) - 1;
    1811       break;
    1812     }
    1813     case MOV_FOURCC('m','d','i','a'): {
    1814       dprintf( "MOV: %*sMedia stream!\n", level, "");
    1815       lschunks(demuxer, level + 1, pos + len, trak);
    1816       break;
    1817     }
    1818     case MOV_FOURCC('m','i','n','f'): {
    1819       dprintf( "MOV: %*sMedia info!\n", level, "");
    1820       lschunks(demuxer, level + 1 ,pos + len, trak);
    1821       break;
    1822     }
    1823     case MOV_FOURCC('s','t','b','l'): {
    1824       dprintf( "MOV: %*sSample info!\n", level, "");
    1825       lschunks(demuxer, level + 1, pos + len, trak);
    1826       break;
    1827     }
    1828     case MOV_FOURCC('e','d','t','s'): {
    1829       dprintf( "MOV: %*sEdit atom!\n", level, "");
    1830       lschunks(demuxer, level + 1, pos + len, trak);
    1831       break;
    1832     }
    1833     case MOV_FOURCC('e','l','s','t'): {
    1834       int temp = stream_read_dword(demuxer->stream);
    1835       int entries = stream_read_dword(demuxer->stream);
    1836       int ver = (temp << 24);
    1837       int flags = (temp << 16) | (temp << 8) | temp;
    1838       int i;
    1839       dprintf(
    1840              "MOV: %*sEdit list table (%d entries) (ver:%d,flags:%d)\n", level, "",
    1841              entries, ver, flags);
    1842 #if 1
    1843       trak->editlist_size = entries;
    1844       trak->editlist = calloc(trak->editlist_size, sizeof(mov_editlist_t));
    1845       for (i = 0; i < entries; i++) {
    1846         int dur = stream_read_dword(demuxer->stream);
    1847         int mt = stream_read_dword(demuxer->stream);
    1848         int mr = stream_read_dword(demuxer->stream); // 16.16fp
    1849         trak->editlist[i].dur = dur;
    1850         trak->editlist[i].pos = mt;
    1851         trak->editlist[i].speed = mr;
    1852         dprintf(
    1853                "MOV: %*s  entry#%d: duration: %d  start time: %d  speed: %3.1fx\n", level, "",
    1854                 i, dur, mt, (float)mr/65536.0f);
    1855       }
    1856 #endif
    1857       break;
    1858     }
    1859     case MOV_FOURCC('c','o','d','e'): {
    1860       /* XXX: Implement atom 'code' for FLASH support */
    1861       break;
    1862     }
    1863     default:
    1864       id = be2me_32(id);
    1865       dprintf("MOV: unknown chunk: %.4s %d\n",(char *)&id,(int)len);
    1866       break;
    1867   }//switch(id)
    1868   return 0;
    1869 }
    1870 
    1871 static demuxer_t* mov_read_header(demuxer_t* demuxer){
    1872     mov_priv_t* priv=demuxer->priv;
    1873     int t_no;
    1874     int best_a_id=-1, best_a_len=0;
    1875     int best_v_id=-1, best_v_len=0;
    1876 
    1877     dprintf( "mov_read_header!\n");
    1878 
    1879     // Parse header:
    1880     stream_reset(demuxer->stream);
    1881     if(!stream_seek(demuxer->stream,priv->moov_start))
    1882     {
    1883         dprintf("MOV: Cannot seek to the beginning of the Movie header (0x%"PRIx64")\n",
    1884             (int64_t)priv->moov_start);
    1885         return 0;
    1886     }
    1887     lschunks(demuxer, 0, priv->moov_end, NULL);
    1888     // just in case we have hit eof while parsing...
    1889     demuxer->stream->eof = 0;
    1890 //    dprintf( "--------------\n");
    1891 
    1892     // find the best (longest) streams:
    1893     for(t_no=0;t_no<priv->track_db;t_no++){
    1894         mov_track_t* trak=priv->tracks[t_no];
    1895         int len=(trak->samplesize) ? trak->chunks_size : trak->samples_size;
    1896         if(demuxer->a_streams[t_no]){ // need audio
    1897             if(len>best_a_len){ best_a_len=len; best_a_id=t_no; }
    1898         }
    1899         if(demuxer->v_streams[t_no]){ // need video
    1900             if(len>best_v_len){ best_v_len=len; best_v_id=t_no; }
    1901         }
    1902     }
    1903     dprintf( "MOV: longest streams: A: #%d (%d samples)  V: #%d (%d samples)\n",
    1904         best_a_id,best_a_len,best_v_id,best_v_len);
    1905     if(demuxer->audio->id==-1 && best_a_id>=0) demuxer->audio->id=best_a_id;
    1906     if(demuxer->video->id==-1 && best_v_id>=0) demuxer->video->id=best_v_id;
    1907 
    1908     // setup sh pointers:
    1909     if(demuxer->audio->id>=0){
    1910         sh_audio_t* sh=demuxer->a_streams[demuxer->audio->id];
    1911         if(sh){
    1912             demuxer->audio->sh=sh; sh->ds=demuxer->audio;
    1913         } else {
    1914             dprintf( "MOV: selected audio stream (%d) does not exists\n",demuxer->audio->id);
    1915             demuxer->audio->id=-2;
    1916         }
    1917     }
    1918     if(demuxer->video->id>=0){
    1919         sh_video_t* sh=demuxer->v_streams[demuxer->video->id];
    1920         if(sh){
    1921             demuxer->video->sh=sh; sh->ds=demuxer->video;
    1922         } else {
    1923             dprintf( "MOV: selected video stream (%d) does not exists\n",demuxer->video->id);
    1924             demuxer->video->id=-2;
    1925         }
    1926     }
    1927 
    1928     if(demuxer->video->id<0 && demuxer->audio->id<0) {
    1929         /* No AV streams found. Try to find an MPEG stream. */
    1930         for(t_no=0;t_no<priv->track_db;t_no++){
    1931             mov_track_t* trak=priv->tracks[t_no];
    1932             if(trak->media_handler == MOV_FOURCC('M','P','E','G')) {
    1933                 stream_t *s;
    1934                 demuxer_t *od;
    1935 
    1936                 demuxer->video->id = t_no;
    1937                 s = new_ds_stream(demuxer->video);
    1938                 od = demux_open(s, DEMUXER_TYPE_MPEG_PS, -1, -1, -1, NULL);
    1939                 if(od) return new_demuxers_demuxer(od, od, od);
    1940                 demuxer->video->id = -2;        //new linked demuxer couldn't be allocated
    1941                 break;
    1942             }
    1943         }
    1944     }
    1945 
    1946 #if 0
    1947     if( mp_msg_test(MSGL_DBG3) ){
    1948         for(t_no=0;t_no<priv->track_db;t_no++){
    1949             mov_track_t* trak=priv->tracks[t_no];
    1950             if(trak->type==MOV_TRAK_GENERIC){
    1951                 int i;
    1952                 int fd;
    1953                 char name[20];
    1954                 dprintf( "MOV: Track #%d: Extracting %d data chunks to files\n",t_no,trak->samples_size);
    1955                 for (i=0; i<trak->samples_size; i++)
    1956                 {
    1957                     int len=trak->samples[i].size;
    1958                     char buf[len];
    1959                     stream_seek(demuxer->stream, trak->samples[i].pos);
    1960                     snprintf(name, 20, "t%02d-s%03d.%s", t_no,i,
    1961                         (trak->media_handler==MOV_FOURCC('f','l','s','h')) ?
    1962                             "swf":"dump");
    1963                     fd = open(name, O_CREAT|O_WRONLY);
    1964 //                  { int j;
    1965 //                      for(j=0;j<trak->stdata_len-3; j++)
    1966 //                          printf("stdata[%d]=0x%X ize=0x%X\n",j,char2int(trak->stdata,j),MOV_FOURCC('z','l','i','b'));
    1967 //                  }
    1968                     if( //trak->media_handler==MOV_FOURCC('s','p','r','t') &&
    1969                         trak->stdata_len>=16 &&
    1970                         char2int(trak->stdata,12)==MOV_FOURCC('z','l','i','b')
    1971                     ){
    1972                         int newlen=stream_read_dword(demuxer->stream);
    1973 #ifdef HAVE_ZLIB
    1974                         // unzip:
    1975                         z_stream zstrm;
    1976                         int zret;
    1977                         char buf2[newlen];
    1978 
    1979                         len-=4;
    1980                         stream_read(demuxer->stream, buf, len);
    1981 
    1982                         zstrm.zalloc          = (alloc_func)0;
    1983                         zstrm.zfree           = (free_func)0;
    1984                         zstrm.opaque          = (voidpf)0;
    1985                         zstrm.next_in         = buf;
    1986                         zstrm.avail_in        = len;
    1987                         zstrm.next_out        = buf2;
    1988                         zstrm.avail_out       = newlen;
    1989 
    1990                         zret = inflateInit(&zstrm);
    1991                         zret = inflate(&zstrm, Z_NO_FLUSH);
    1992                         if(newlen != zstrm.total_out)
    1993                             dprintf( "Warning! unzipped frame size differs hdr: %d  zlib: %ld\n",newlen,zstrm.total_out);
    1994 
    1995                         write(fd, buf2, newlen);
    1996                     } else {
    1997 #else
    1998                         len-=4;
    1999                         dprintf( "******* ZLIB COMPRESSED SAMPLE!!!!! (%d->%d bytes) *******\n",len,newlen);
    2000                     }
    2001                     {
    2002 #endif
    2003                         stream_read(demuxer->stream, buf, len);
    2004                         write(fd, buf, len);
    2005                     }
    2006                     close(fd);
    2007                 }
    2008             }
    2009         }
    2010     }
    2011     demuxer->stream->eof = 0;
    2012 #endif
    2013 
    2014     return demuxer;
    2015 }
    2016 
    2017 /**
    2018  * \brief return the mov track that belongs to a demuxer stream
    2019  * \param ds the demuxer stream, may be NULL
    2020  * \return the mov track info structure belonging to the stream,
    2021  *          NULL if not found
    2022  */
    2023 static mov_track_t *stream_track(mov_priv_t *priv, demux_stream_t *ds) {
    2024   if (ds && (ds->id >= 0) && (ds->id < priv->track_db))
    2025     return priv->tracks[ds->id];
    2026   return NULL;
    2027 }
    2028 
    2029 // return value:
    2030 //     0 = EOF or no stream found
    2031 //     1 = successfully read a packet
    2032 static int demux_mov_fill_buffer(demuxer_t *demuxer,demux_stream_t* ds){
    2033     mov_priv_t* priv=demuxer->priv;
    2034     mov_track_t* trak=NULL;
    2035     float pts;
    2036     int x;
    2037     off_t pos;
    2038 
    2039     if (ds->eof) return 0;
    2040     trak = stream_track(priv, ds);
    2041     if (!trak) return 0;
    2042 
    2043 if(trak->samplesize){
    2044     // read chunk:
    2045     if(trak->pos>=trak->chunks_size) return 0; // EOF
    2046     stream_seek(demuxer->stream,trak->chunks[trak->pos].pos);
    2047     pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale;
    2048     if(trak->samplesize!=1)
    2049     {
    2050         dprintf( "WARNING! Samplesize(%d) != 1\n",
    2051                 trak->samplesize);
    2052         if((trak->fourcc != MOV_FOURCC('t','w','o','s')) && (trak->fourcc != MOV_FOURCC('s','o','w','t')))
    2053             x=trak->chunks[trak->pos].size*trak->samplesize;
    2054         else
    2055             x=trak->chunks[trak->pos].size;
    2056     }
    2057     x=trak->chunks[trak->pos].size;
    2058 //    printf("X = %d\n", x);
    2059     /* the following stuff is audio related */
    2060     if (trak->type == MOV_TRAK_AUDIO){
    2061       if(trak->stdata_len>=44 && trak->stdata[9]>=1 && char2int(trak->stdata,28)>0){
    2062         // stsd version 1 - we have audio compression ratio info:
    2063         x/=char2int(trak->stdata,28); // samples/packet
    2064 //      x*=char2int(trak->stdata,32); // bytes/packet
    2065         x*=char2int(trak->stdata,36); // bytes/frame
    2066       } else {
    2067         if(ds->ss_div && ds->ss_mul){
    2068             // workaround for buggy files like 7up-high-traffic-areas.mov,
    2069             // with missing stsd v1 header containing compression rate
    2070             x/=ds->ss_div; x*=ds->ss_mul; // compression ratio fix  ! HACK !
    2071         } else {
    2072             x*=trak->nchannels;
    2073             x*=trak->samplebytes;
    2074         }
    2075       }
    2076       dprintf( "Audio sample %d bytes pts %5.3f\n",trak->chunks[trak->pos].size*trak->samplesize,pts);
    2077     } /* MOV_TRAK_AUDIO */
    2078     pos=trak->chunks[trak->pos].pos;
    2079 } else {
    2080     int frame=trak->pos;
    2081     // editlist support:
    2082     if(trak->type == MOV_TRAK_VIDEO && trak->editlist_size>=1){
    2083         // find the right editlist entry:
    2084         if(frame<trak->editlist[trak->editlist_pos].start_frame)
    2085             trak->editlist_pos=0;
    2086         while(trak->editlist_pos<trak->editlist_size-1 &&
    2087             frame>=trak->editlist[trak->editlist_pos+1].start_frame)
    2088                 ++trak->editlist_pos;
    2089         if(frame>=trak->editlist[trak->editlist_pos].start_frame+
    2090             trak->editlist[trak->editlist_pos].frames) return 0; // EOF
    2091         // calc real frame index:
    2092         frame-=trak->editlist[trak->editlist_pos].start_frame;
    2093         frame+=trak->editlist[trak->editlist_pos].start_sample;
    2094         // calc pts:
    2095         pts=(float)(trak->samples[frame].pts+
    2096             trak->editlist[trak->editlist_pos].pts_offset)/(float)trak->timescale;
    2097     } else {
    2098         if(frame>=trak->samples_size) return 0; // EOF
    2099         pts=(float)trak->samples[frame].pts/(float)trak->timescale;
    2100     }
    2101     // read sample:
    2102     stream_seek(demuxer->stream,trak->samples[frame].pos);
    2103     x=trak->samples[frame].size;
    2104     pos=trak->samples[frame].pos;
    2105 }
    2106 if(trak->pos==0 && trak->stream_header_len>0){
    2107     // we have to append the stream header...
    2108     demux_packet_t* dp=new_demux_packet(x+trak->stream_header_len);
    2109     memcpy(dp->buffer,trak->stream_header,trak->stream_header_len);
    2110     stream_read(demuxer->stream,dp->buffer+trak->stream_header_len,x);
    2111     free(trak->stream_header);
    2112     trak->stream_header = NULL;
    2113     trak->stream_header_len = 0;
    2114     dp->pts=pts;
    2115     dp->flags=0;
    2116     dp->pos=pos; // FIXME?
    2117     ds_add_packet(ds,dp);
    2118 } else
    2119     ds_read_packet(ds,demuxer->stream,x,pts,pos,0);
    2120 
    2121     ++trak->pos;
    2122 
    2123     return 1;
    2124 
    2125 }
    2126 
    2127 static float mov_seek_track(mov_track_t* trak,float pts,int flags){
    2128 
    2129 //    printf("MOV track seek called  %5.3f  \n",pts);
    2130     if(flags&2) pts*=trak->length; else pts*=(float)trak->timescale;
    2131 
    2132 if(trak->samplesize){
    2133     int sample=pts/trak->duration;
    2134 //    printf("MOV track seek - chunk: %d  (pts: %5.3f  dur=%d)  \n",sample,pts,trak->duration);
    2135     if(!(flags&1)) sample+=trak->chunks[trak->pos].sample; // relative
    2136     trak->pos=0;
    2137     while(trak->pos<trak->chunks_size && trak->chunks[trak->pos].sample<sample) ++trak->pos;
    2138     if (trak->pos == trak->chunks_size) return -1;
    2139     pts=(float)(trak->chunks[trak->pos].sample*trak->duration)/(float)trak->timescale;
    2140 } else {
    2141     unsigned int ipts;
    2142     if(!(flags&1)) pts+=trak->samples[trak->pos].pts;
    2143     if(pts<0) pts=0;
    2144     ipts=pts;
    2145     //printf("MOV track seek - sample: %d  \n",ipts);
    2146     for(trak->pos=0;trak->pos<trak->samples_size;++trak->pos){
    2147         if(trak->samples[trak->pos].pts>=ipts) break; // found it!
    2148     }
    2149     if (trak->pos == trak->samples_size) return -1;
    2150     if(trak->keyframes_size){
    2151         // find nearest keyframe
    2152         int i;
    2153         for(i=0;i<trak->keyframes_size;i++){
    2154             if(trak->keyframes[i]>=trak->pos) break;
    2155         }
    2156         if (i == trak->keyframes_size) return -1;
    2157         if(i>0 && (trak->keyframes[i]-trak->pos) > (trak->pos-trak->keyframes[i-1]))
    2158           --i;
    2159         trak->pos=trak->keyframes[i];
    2160 //      printf("nearest keyframe: %d  \n",trak->pos);
    2161     }
    2162     pts=(float)trak->samples[trak->pos].pts/(float)trak->timescale;
    2163 }
    2164 
    2165 //    printf("MOV track seek done:  %5.3f  \n",pts);
    2166 
    2167 return pts;
    2168 }
    2169 
    2170 static void demux_seek_mov(demuxer_t *demuxer,float pts,int flags){
    2171     mov_priv_t* priv=demuxer->priv;
    2172     demux_stream_t* ds;
    2173     mov_track_t* trak;
    2174 
    2175 //    printf("MOV seek called  %5.3f  flag=%d  \n",pts,flags);
    2176 
    2177     ds=demuxer->video;
    2178     trak = stream_track(priv, ds);
    2179     if (trak) {
    2180         //if(flags&2) pts*=(float)trak->length/(float)trak->timescale;
    2181         //if(!(flags&1)) pts+=ds->pts;
    2182         ds->pts=mov_seek_track(trak,pts,flags);
    2183         if (ds->pts < 0) ds->eof = 1;
    2184         else pts = ds->pts;
    2185         flags=1; // absolute seconds
    2186     }
    2187 
    2188     ds=demuxer->audio;
    2189     trak = stream_track(priv, ds);
    2190     if (trak) {
    2191         //if(flags&2) pts*=(float)trak->length/(float)trak->timescale;
    2192         //if(!(flags&1)) pts+=ds->pts;
    2193         ds->pts=mov_seek_track(trak,pts,flags);
    2194         if (ds->pts < 0) ds->eof = 1;
    2195         if (demuxer->video->id < 0)
    2196           ((sh_audio_t*)ds->sh)->delay = ds->pts;
    2197     }
    2198 
    2199 }
    2200 
    2201 static int demux_mov_control(demuxer_t *demuxer, int cmd, void *arg){
    2202   mov_track_t* track;
    2203 
    2204   // try the video track
    2205   track = stream_track(demuxer->priv, demuxer->video);
    2206   if (!track || !track->length)
    2207     // otherwise try to get the info from the audio track
    2208     track = stream_track(demuxer->priv, demuxer->audio);
    2209 
    2210   if (!track || !track->length)
    2211     return DEMUXER_CTRL_DONTKNOW;
    2212 
    2213   switch(cmd) {
    2214     case DEMUXER_CTRL_GET_TIME_LENGTH:
    2215       if (!track->timescale)
    2216         return DEMUXER_CTRL_DONTKNOW;
    2217       *((double *)arg) = (double)track->length / track->timescale;
    2218       return DEMUXER_CTRL_OK;
    2219 
    2220     case DEMUXER_CTRL_GET_PERCENT_POS:
    2221       {
    2222         off_t pos = track->pos;
    2223         if (track->durmap_size >= 1)
    2224           pos *= track->durmap[0].dur;
    2225         *((int *)arg) = (int)(100 * pos / track->length);
    2226         return DEMUXER_CTRL_OK;
    2227       }
    2228   }
    2229   return DEMUXER_CTRL_NOTIMPL;
    2230 }
    2231 
    2232 
    2233 demuxer_desc_t demuxer_desc_mov = {
    2234   "Quicktime/MP4 demuxer",
    2235   "mov",
    2236   "Quicktime/MOV",
    2237   "Arpi, Al3x, Atmos, others",
    2238   "Handles Quicktime, MP4, 3GP",
    2239   DEMUXER_TYPE_MOV,
    2240   0, // slow autodetect
    2241   mov_check_file,
    2242   demux_mov_fill_buffer,
    2243   mov_read_header,
    2244   demux_close_mov,
    2245   demux_seek_mov,
    2246   demux_mov_control
    2247 };
     2310
     2311
     2312    demuxer_desc_t demuxer_desc_mov = {
     2313        "Quicktime/MP4 demuxer",
     2314        "mov",
     2315        "Quicktime/MOV",
     2316        "Arpi, Al3x, Atmos, others",
     2317        "Handles Quicktime, MP4, 3GP",
     2318        DEMUXER_TYPE_MOV,
     2319        1, // slow autodetect
     2320        mov_check_file,
     2321        demux_mov_fill_buffer,
     2322        mov_read_header,
     2323        demux_close_mov,
     2324        demux_seek_mov,
     2325        demux_mov_control
     2326    };
Note: See TracChangeset for help on using the changeset viewer.