Esempio n. 1
0
/**
 * \fn compute the minimum us delta = maximum fps
 * \brief average fps is not good enough, it might be too high
 * @return 
 */
bool MP4Header::refineFps(void)
{
    int n=VDEO.nbIndex;
    uint64_t minDelta=60*1000*1000;
    for(int i=0;i<n-1;i++)
    {
        MP4Index *dex=&(_tracks[0].index[i]);
        MP4Index *next=&(_tracks[0].index[i+1]);
        if(dex->dts==ADM_NO_PTS) continue;
        if(next->dts==ADM_NO_PTS) continue;
        uint64_t delta=next->dts-dex->dts;
        if(delta<minDelta) minDelta=delta;
    }
    if(minDelta>1000)
    {
        double f=1000000./(double)minDelta;
        f*=1000.;
        ADM_info("MinDelta=%d us\n",(int)minDelta);
        ADM_info("Computed fps1000=%d\n",(int)f);
        uint32_t fps1000=floor(f+0.49);
        if(fps1000>  _videostream.dwRate)
        {
            ADM_info("Adjusting fps, the computed is higher than average, dropped frames ?\n");
           _videostream.dwRate=fps1000;
           _mainaviheader.dwMicroSecPerFrame=ADM_UsecFromFps1000(_videostream.dwRate);
        }
    }
    
}
Esempio n. 2
0
/**
    \fn updateIncrement
    \brief FPS->TimeIncrement
*/
bool resampleFps::updateIncrement(void)
{
    float f=configuration.newFpsNum*1000;
    f/=configuration.newFpsDen;
    info.frameIncrement=ADM_UsecFromFps1000((uint32_t)f);
  
    return true;
}
/**
        \fn mx_mainHeaderFromVideoStream
        \brief Write MainAVIHeader from video
*/
void mx_mainHeaderFromVideoStream(MainAVIHeader  *header,ADM_videoStream *video)
{
    memset(header,0,sizeof(*header));
    header->dwMicroSecPerFrame= ADM_UsecFromFps1000(video->getAvgFps1000()); //int32_t	dwMicroSecPerFrame;	// frame display rate (or 0L)
    header->dwMaxBytesPerSec=8*1000*1000; //int32_t	dwMaxBytesPerSec;	// max. transfer rate
    header->dwPaddingGranularity=0; //int32_t	dwPaddingGranularity;	// pad to multiples of this
					// size; normally 2K.
    header->dwFlags= AVIF_HASINDEX + AVIF_ISINTERLEAVED; // FIXME HAS INDEX //int32_t	dwFlags;		// the ever-present flags
    //header->dwTotalFrames=0; //int32_t	dwTotalFrames;		// # frames in file
    header->dwInitialFrames=0; //int32_t	dwInitialFrames;
   // Must be set by caller  header->dwStreams=int32_t	dwStreams;
    header->dwSuggestedBufferSize=64*1024;// int32_t	dwSuggestedBufferSize;

    header->dwWidth=video->getWidth();//int32_t	dwWidth;
    header->dwHeight=video->getHeight();//int32_t	dwHeight;
}
/**
        \fn parseStbl
        \brief parse sample table. this is the most important function.
*/
uint8_t       MP4Header::parseStbl(void *ztom,uint32_t trackType,uint32_t w,uint32_t h,uint32_t trackScale)
{
  adm_atom *tom=(adm_atom *)ztom;
  ADMAtoms id;
  uint32_t container;
  MPsampleinfo  info;
  
  
  memset(&info,0,sizeof(info));

  
  printf("<<Parsing Stbl>>\n");
  while(!tom->isDone())
  {
     adm_atom son(tom);
     if(!ADM_mp4SearchAtomName(son.getFCC(), &id,&container))
     {
       adm_printf(ADM_PRINT_DEBUG,"[STBL]Found atom %s unknown\n",fourCC::tostringBE(son.getFCC()));
       son.skipAtom();
       continue;
     }
     switch(id)
     {
       case ADM_MP4_STSS:  // Sync sample atom (i.e. keyframes)
       {
          son.read32();
          info.nbSync=son.read32();
          printf("Stss:%u\n",info.nbSync);
          if(info.nbSync)
          {
                  info.Sync=new uint32_t[info.nbSync];
                  for(int i=0;i<info.nbSync;i++)
                  {
                          info.Sync[i]=son.read32();
                  }
          }
          break;
         
       }
       case ADM_MP4_STTS: 
            {
                printf("stts:%lu\n",son.read32()); // version & flags
                info.nbStts=son.read32();
                printf("Time stts atom found (%lu)\n",info.nbStts);
                printf("Using myscale %lu\n",trackScale);
                info.SttsN=new uint32_t[info.nbStts];
                info.SttsC=new uint32_t[info.nbStts];
                double dur;
                for(int i=0;i<info.nbStts;i++)
                {
                        
                        info.SttsN[i]=son.read32();
                        info.SttsC[i]=son.read32();
                        adm_printf(ADM_PRINT_VERY_VERBOSE,"stts: count:%u size:%u (unscaled)\n",info.SttsN[i],info.SttsC[i]);	
                        //dur*=1000.*1000.;; // us
                        //dur/=myScale;
                }                
            }
            break;
       case ADM_MP4_STSC:
            {
                son.read32();
                info.nbSc=son.read32();
                info.Sc=new uint32_t[info.nbSc];
                info.Sn=new uint32_t[info.nbSc];
                for(int j=0;j<info.nbSc;j++)
                {

                        info.Sc[j]=son.read32();
                        info.Sn[j]=son.read32();
                        son.read32();
                        adm_printf(ADM_PRINT_VERY_VERBOSE,"\t sc  %d : sc start:%u sc count: %u\n",j,info.Sc[j],info.Sn[j]);
                }

            }
            break;
       case ADM_MP4_STSZ:
          {
            uint32_t n;
              son.read32();
              n=son.read32();
              info.nbSz=son.read32();
              info.SzIndentical=0;
              printf("%lu frames /%lu nbsz..\n",n,info.nbSz);
              if(n)
                      {
                            adm_printf(ADM_PRINT_VERY_VERBOSE,"\t\t%lu frames of the same size %lu , n=%lu\n",
                                info.nbSz,info.SzIndentical,n);
                            info.SzIndentical=n;
                            info.Sz=NULL;
                      }
              else
              {
                      info.Sz=new uint32_t[info.nbSz];
                      for(int j=0;j<info.nbSz;j++)
                      {
                                      info.Sz[j]=son.read32();
                      }
              }
          }
          break;
           case ADM_MP4_CTTS: // Composition time to sample             
            {
                uint32_t n,i,j,k,v;
                
                  printf("ctts:%lu\n",son.read32()); // version & flags
                  n=son.read32();
                  if(n==1) // all the same , ignore
                  {
                    break;
                  }
                uint32_t *values=new uint32_t [n];
                uint32_t *count=new uint32_t [n];
                for(i=0;i<n;i++)
                {
                    count[i]=son.read32();
                    values[i]=son.read32();
                }
                uint32_t sum=0;
                for(i=0;i<n;i++)
                {
                    sum+=count[i];
                }
                info.Ctts=new uint32_t[sum+1]; // keep a safe margin
                
                for(i=0;i<n;i++)
                {
                    if(i<20)
                    {
                        adm_printf(ADM_PRINT_VERY_VERBOSE,"Ctts: nb: %u (%x) val:%u (%x)\n",count[i],count[i],values[i],values[i]);   
                    }
                    for(k=0;k<count[i];k++)
                    {
                        info.Ctts[info.nbCtts++]=values[i];
                    }
                }
                delete [] values;
                delete [] count;
                if(!info.nbCtts)
                {
                    delete [] info.Ctts;
                    info.Ctts=NULL;
                    printf("Destroying Ctts, seems invalid\n");
                }
                ADM_assert(info.nbCtts<sum+1);
                printf("Found %u elements\n",info.nbCtts);
            }
            break;  
       case ADM_MP4_STCO:
       {
          son.read32();
          info.nbCo=son.read32();
          printf("\t\tnbCo:%u\n",info.nbCo);
          info.Co=new uint32_t[info.nbCo];
          for(int j=0;j< info.nbCo;j++)
          {
                  info.Co[j]=son.read32();
                  adm_printf(ADM_PRINT_VERY_VERBOSE,"Chunk offset : %u / %u  : %u\n",  j,info.nbCo,info.Co[j]);
          }

       }
       break;
       case ADM_MP4_STCO64:
       {
         printf("Incomplete support for 64 bits quicktime!!\n");
          son.read32();
          info.nbCo=son.read32();
          printf("\t\tnbCo:%u\n",info.nbCo);
          info.Co=new uint32_t[info.nbCo];
          for(int j=0;j< info.nbCo;j++)
          {
                  son.read32(); // Ignore MSB
                  info.Co[j]=son.read32();
                  adm_printf(ADM_PRINT_VERY_VERBOSE,"Chunk offset : %u / %u  : %lu\n",  j,info.nbCo,info.Co[j]);
          }

       }
       break;
       case ADM_MP4_STSD:
       {
                son.read32(); // flags & version
                int nbEntries=son.read32();
                int left;
                adm_printf(ADM_PRINT_DEBUG,"[STSD]Found %d entries\n",nbEntries);
                for(int i=0;i<nbEntries;i++)
                {
                   int entrySize=son.read32();
                   int entryName=son.read32();
                   left=entrySize-8;
                   if(i || (trackType==TRACK_VIDEO && _videoFound) || (trackType==TRACK_OTHER))
                   {
                    son.skipBytes(left); 
                    printf("[STSD] ignoring %s, size %u\n",fourCC::tostringBE(entryName),entrySize);
                    if(trackType==TRACK_OTHER) printf("[STSD] because track=other\n");
                    continue;
                   }
                   switch(trackType)
                   {
                     case TRACK_VIDEO:
                     {
                          uint32_t lw=0,lh=0;
                                printf("[STSD] VIDEO %s, size %u\n",fourCC::tostringBE(entryName),entrySize);
                                son.skipBytes(8);  // reserved etc..
                                left-=8;
                                son.read32(); // version/revision
                                left-=4;
                                printf("[STSD] vendor %s\n",fourCC::tostringBE(son.read32()));
                                left-=4;
                                
                                son.skipBytes(8); // spatial qual etc..
                                left-=8;
                                
                                printf("[STSD] width :%u\n",lw=son.read16());
                                printf("[STSD] height :%u\n",lh=son.read16());
                                left-=4;
                                
                                son.skipBytes(8); // Resolution
                                left-=8;
                                
                                printf("[STSD] datasize :%u\n",son.read32());
                                left-=4;
                     
                                printf("[STSD] FrameCount :%u\n",son.read16());
                                left-=4;
                                
                                // Codec name
                                uint32_t u32=son.read();
                                if(u32>31) u32=31;
                                printf("Codec string :%d <",u32);
                                for(int i=0;i<u32;i++) printf("%c",son.read());
                                printf(">\n");
                                son.skipBytes(32-1-u32);
                                left-=32;
                                // 
                                son.read32();
                                left-=4; //Depth & color Id
                                //
                                printf("LEFT:%d\n",left);
                                
                                if(left>8)
                                {
//                                  decodeVideoAtom(&son); 
                                }
                                //
#define commonPart(x)             _videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t *)#x);
                      

                                 _video_bih.biWidth=_mainaviheader.dwWidth=lw ; 
                                  _video_bih.biHeight=_mainaviheader.dwHeight=lh; 
                                  _video_bih.biCompression=_videostream.fccHandler;

                                //
                                switch(entryName)
                                {
                                  case MKFCCR('m','j','p','b'):  //mjpegb
                                  {
                                        commonPart(MJPB);
                                        left=0;
                                  }
                                  break;
                                case MKFCCR('s','2','6','3'):  //s263 d263
                                  {
                                        commonPart(H263);
                                         adm_atom d263(&son);
                                         printf("Reading s253, got %s\n",fourCC::tostringBE(d263.getFCC()));
                                          left=0;
                                  }
                                  break;
                                   case MKFCCR('m','p','4','v'):  //mp4v
                                  {
                                        commonPart(DIVX);
                                         adm_atom esds(&son);
                                         printf("Reading esds, got %s\n",fourCC::tostringBE(esds.getFCC()));
                                         if(esds.getFCC()==MKFCCR('e','s','d','s'))
                                              decodeEsds(&esds,TRACK_VIDEO);
                                          left=0;
                                  }
                                        break;
                                  case MKFCCR('S','V','Q','3'):
                                  {//'SVQ3':
                                    // For SVQ3, the codec needs it to begin by SVQ3
                                    // We go back by 4 bytes to get the 4CC
                                            printf("SVQ3 atom found\n");
                                            VDEO.extraDataSize=left+4;
                                            VDEO.extraData=new uint8_t[ VDEO.extraDataSize ];
                                            if(!son.readPayload(VDEO.extraData+4,VDEO.extraDataSize-4 ))
                                            {
                                              GUI_Error_HIG(QT_TR_NOOP("Problem reading SVQ3 headers"), NULL);
                                            }
                                            VDEO.extraData[0]='S';
                                            VDEO.extraData[1]='V';
                                            VDEO.extraData[2]='Q';
                                            VDEO.extraData[3]='3';
                                            printf("SVQ3 Header size : %lu",_videoExtraLen);
                                            commonPart(SVQ3);
                                            left=0;
                                  }
                                            break;
                                  case MKFCCR('d','v','c',' ') : //'dvc ':
                                  case MKFCCR('d','v','c','p'): //'dvcp':
                                          commonPart(DVDS);
                                          break;
                                  case MKFCCR('c','v','i','d'): //'cvid'
                                          commonPart(cvid);
                                          break;
                                  case MKFCCR('h','2','6','3'): //'dv':
                                          commonPart(H263);
                                          break;
                                  case MKFCCR('M','J','P','G'): //'jpeg':
                                  case MKFCCR('j','p','e','g'): //'jpeg':
                                  case MKFCCR('A','V','D','J'): //'jpeg':
                                          commonPart(MJPG);
                                          break;
                                  case MKFCCR('a','v','c','1'): // avc1
                                          {
                                          commonPart(H264);
                                          // There is a avcC atom just after
                                          // configuration data for h264
                                          adm_atom avcc(&son);
                                          printf("Reading avcC, got %s\n",fourCC::tostringBE(avcc.getFCC()));
                                          int len,offset;
                                          VDEO.extraDataSize=avcc.getRemainingSize();
                                          VDEO.extraData=new uint8_t [VDEO.extraDataSize];
                                          avcc.readPayload(VDEO.extraData,VDEO.extraDataSize);
                                          printf("avcC size:%d\n",VDEO.extraDataSize);
                                    // Dump some info
                                        #define MKD8(x) VDEO.extraData[x]
                                        #define MKD16(x) ((MKD8(x)<<8)+MKD8(x+1))
                                        #define MKD32(x) ((MKD16(x)<<16)+MKD16(x+2))

                                            printf("avcC Revision             :%x\n", MKD8(0));
                                            printf("avcC AVCProfileIndication :%x\n", MKD8(1));
                                            printf("avcC profile_compatibility:%x\n", MKD8(2));
                                            printf("avcC AVCLevelIndication   :%x\n", MKD8(3));
        
                                            printf("avcC lengthSizeMinusOne   :%x\n", MKD8(4));
                                            printf("avcC NumSeq               :%x\n", MKD8(5));
                                            len=MKD16(6);
                                            printf("avcC sequenceParSetLen    :%x ",len );
                                            offset=8;
                                            mixDump(VDEO.extraData+offset,len);
        
                                            offset=8+len;
                                            printf("\navcC numOfPictureParSets  :%x\n", MKD8(offset++));
                                            len=MKD16(offset++);
                                            printf("avcC Pic len              :%x\n",len);
                                            mixDump(VDEO.extraData+offset,len);
                                            left=0;
                                            }
                                            break;
                                  default:
                                            if(left>10)
                                            {
                                                adm_atom avcc(&son);
                                                printf("Reading , got %s\n",fourCC::tostringBE(avcc.getFCC()));
                                                left=0;
                                                
                                            }
                                            break;
                                } // Entry name
                     }
                     break;
                     case TRACK_AUDIO:
                     {
                        uint32_t channels,bpp,encoding,fq,packSize;
                        
                                // Put some defaults
                                ADIO.encoding=1234;
                                ADIO.frequency=44100;
                                ADIO.byterate=128000>>3;
                                ADIO.channels=2;
                                ADIO.bitspersample=16;
                        
                                printf("[STSD] AUDIO <%s>, 0x%08x, size %u\n",fourCC::tostringBE(entryName),entryName,entrySize);
                                son.skipBytes(8);  // reserved etc..
                                left-=8;
                                
                                int atomVersion=son.read16();  // version
                                left-=2;
                                printf("[STSD]Revision       :%d\n",atomVersion);
                                son.skipBytes(2);  // revision
                                left-=2;
                                
                                printf("[STSD]Vendor         : %s\n",fourCC::tostringBE(son.read32()));
                                left-=4;
                                
                                ADIO.channels=channels=son.read16(); // Channel
                                left-=2;
                                printf("[STSD]Channels       :%d\n",ADIO.channels);
                                ADIO.bitspersample=bpp=son.read16(); // version/revision
                                left-=2;
                                printf("[STSD]Bit per sample :%d\n",bpp);
                                
                                encoding=son.read16(); // version/revision
                                left-=2;
                                printf("[STSD]Encoding       :%d\n",encoding);

                                packSize=son.read16(); // Packet Size
                                left-=2;
                                printf("[STSD]Packet size    :%d\n",encoding);
                                
                              
                                fq=ADIO.frequency=son.read16();
                                printf("[STSD]Fq:%u\n",fq);
                                if(ADIO.frequency<6000) ADIO.frequency=48000;
                                printf("[STSD]Fq       :%d\n",ADIO.frequency); // Bps
                                        son.skipBytes(2); // Fixed point
                                left-=4;
                                if(atomVersion)
                                {
                                    info.samplePerPacket=son.read32();
                                    info.bytePerPacket=son.read32();
                                    info.bytePerFrame=son.read32();
                                    printf("[STSD] Sample per packet %u\n",info.samplePerPacket);
                                    printf("[STSD] Bytes per packet  %u\n",info.bytePerPacket);
                                    printf("[STSD] Bytes per frame   %u\n",info.bytePerFrame);
                                    printf("[STSD] Bytes per sample   %u\n",son.read32());
                                    left-=16;
                                }else
                                {
                                  info.samplePerPacket=1;
                                  info.bytePerPacket=1;
                                  info.bytePerFrame=1;
                                }
                                switch(atomVersion)
                                {
                                  case 0:break;
                                  case 1: break;
                                  case 2:
                                          ADIO.frequency=44100; // FIXME
                                          ADIO.channels=son.read32();
                                          printf("Channels            :%d\n",ADIO.channels); // Channels
                                          printf("Tak(7F000)          :%x\n",son.read32()); // Channels
                                          printf("Bits  per channel   :%d\n",son.read32());  // Vendor
                                          printf("Format specific     :%x\n",son.read32());  // Vendor
                                          printf("Byte per audio packe:%x\n",son.read32());  // Vendor
                                          printf("LPCM                :%x\n",son.read32());  // Vendor
                                          left-=(5*4+4+16);
                                          break;
                                }
                                printf("[STSD] chan:%u bpp:%u encoding:%u fq:%u (left %u)\n",channels,bpp,encoding,fq,left);
#define audioCodec(x) ADIO.encoding=WAV_##x;
                                switch(entryName)
                                {
                                    
                                    case MKFCCR('t','w','o','s'):
                                            audioCodec(LPCM);
                                            ADIO.byterate=ADIO.frequency*ADIO.bitspersample*ADIO.channels/8;
                                            break;
                                                
                                    case MKFCCR('u','l','a','w'):
                                            audioCodec(ULAW);
                                            ADIO.byterate=ADIO.frequency;
                                            break;
                                    case MKFCCR('s','o','w','t'):
                                            audioCodec(PCM);
                                            ADIO.byterate=ADIO.frequency*ADIO.bitspersample*ADIO.channels/8;
                                            break;
                                    case MKFCCR('.','m','p','3'): //.mp3
                                            audioCodec(MP3);
                                            ADIO.byterate=128000>>3;
                                            break;
                                    case MKFCCR('r','a','w',' '):
                                            audioCodec(8BITS_UNSIGNED);
                                            ADIO.byterate=ADIO.frequency*ADIO.channels;
                                            break;
                                    case MKFCCR('s','a','m','r'):
                                    {
                                            audioCodec(AMRNB);
                                            ADIO.frequency=8000;
                                            ADIO.channels=1;
                                            ADIO.bitspersample=16;
                                            ADIO.byterate=12000/8;
                                            if(left>10)
                                            {
                                               adm_atom amr(&son);
                                              printf("Reading wave, got %s\n",fourCC::tostringBE(amr.getFCC()));
                                              left=0;
                                            }
                                    }
                                            break;
                                    case MKFCCR('Q','D','M','2'):
                                        {
                                            uint32_t sz;
                                              audioCodec(QDM2);
                                              sz=son.getRemainingSize();
                                              _tracks[1+nbAudioTrack].extraDataSize=sz;
                                              _tracks[1+nbAudioTrack].extraData=new uint8_t[sz];
                                              son.readPayload(_tracks[1+nbAudioTrack].extraData,sz);
                                              left=0;
                                        }
                                        break;
                                    case MKFCCR('m','s',0,0x55): // why 55 ???
                                    case MKFCCR('m','p','4','a'):
                                    {
                                              audioCodec(AAC);
                                            if(left>10)
                                            {
                                              adm_atom wave(&son);
                                              printf("Reading wave, got %s\n",fourCC::tostringBE(wave.getFCC()));
                                              if(MKFCCR('w','a','v','e')==wave.getFCC())
                                              {
                                                 // mp4a
                                                 //   wave
                                                 //     frma
                                                 //     mp4a
                                                 //     esds
                                                 while(!wave.isDone())
                                                 {
                                                     adm_atom item(&wave);
                                                     printf("parsing wave, got %s,0x%x\n",fourCC::tostringBE(item.getFCC()),
                                                                  item.getFCC());
                                                     switch(item.getFCC())
                                                     {
                                                       case MKFCCR('f','r','m','a'):
                                                          {
                                                          uint32_t codecid=item.read32();
                                                          printf("frma Codec Id :%s\n",fourCC::tostringBE(codecid));
                                                          }
                                                          break;
                                                       case MKFCCR('m','s',0,0x55):
                                                        {
                                                          // We have a waveformat here
                                                          printf("[STSD]Found MS audio header:\n");
                                                          ADIO.encoding=ADM_swap16(item.read16());
                                                          ADIO.channels=ADM_swap16(item.read16());
                                                          ADIO.frequency=ADM_swap32(item.read32());
                                                          ADIO.byterate=ADM_swap32(item.read32());
                                                          ADIO.blockalign=ADM_swap16(item.read16());
                                                          ADIO.bitspersample=ADM_swap16(item.read16());
                                                          printWavHeader(&(ADIO));
                                                          
                                                        }
                                                       break;
                                                        case MKFCCR('m','p','4','a'):
                                                          break; 
                                                        case MKFCCR('e','s','d','s'):
                                                          {
                                                               decodeEsds(&item,TRACK_AUDIO);
                                                          goto foundit; // FIXME!!!
                                                          }
                                                          break;
                                                       default:
                                                         break;
                                                     }

                                                     item.skipAtom();
                                                   
                                                 }  // Wave iddone
                                                 left=0;
                                              }  // if ==wave
                                              else
                                              {
                                                if(wave.getFCC()==MKFCCR('e','s','d','s'))
                                                          {
                                                               decodeEsds(&wave,TRACK_AUDIO);
                                                               goto foundit; // FIXME!!!
                                                          } 
                                                else
                                                {
                                                  printf("UNHANDLED ATOM : %s\n",fourCC::tostringBE(wave.getFCC())); 
                                                }
                                              }
                                            } // if left > 10
foundit: // HACK FIXME     
                                            left=0;
                                    }       
                                            break; // mp4a
                                  
                                }
                     }
                          break;
                     default:
                          ADM_assert(0);
                   }
                   son.skipBytes(left); 
                }
       }
              break;
       default:
          printf("[STBL]Skipping atom %s\n",fourCC::tostringBE(son.getFCC()));
     }
     son.skipAtom();
  }
  uint8_t r=0;
  uint32_t nbo=0;
  switch(trackType)
  {
    case TRACK_VIDEO:
        {
          if(_tracks[0].index)
          {
              printf("Already got a video track\n");
              return 1;
          }
          r=indexify(&(_tracks[0]),trackScale,&info,0,&nbo);
          
          _videostream.dwLength= _mainaviheader.dwTotalFrames=_tracks[0].nbIndex;
          // update fps
          float f=_videostream.dwLength;
          if(_movieDuration) f=1000000.*f/_movieDuration;
              else  f=25000;
          _videostream.dwRate=(uint32_t)floor(f);
           _mainaviheader.dwMicroSecPerFrame=ADM_UsecFromFps1000(_videostream.dwRate);
          // if we have a sync atom ???
          if(info.nbSync)
          {
            // Mark keyframes
            for(int i=0;i<info.nbSync;i++)
            {
              int sync=info.Sync[i];
              if(sync) sync--;
              _tracks[0].index[sync].intra=AVI_KEY_FRAME;
            }
          }
          else
          { // All frames are kf
            for(int i=0;i<_tracks[0].nbIndex;i++)
            {
              _tracks[0].index[i].intra=AVI_KEY_FRAME;
            }
          }
          // Now do the CTTS thing
          if(info.Ctts)
          {
            updateCtts(&info);
          }

          
           VDEO.index[0].intra=AVI_KEY_FRAME;
        }
          break;
    case TRACK_AUDIO:
          printf("Cur audio track :%u\n",nbAudioTrack);
          if(info.SzIndentical ==1 && (ADIO.encoding==WAV_LPCM || ADIO.encoding==WAV_PCM ))
            {
              printf("Overriding size %lu -> %lu\n", info.SzIndentical,info.SzIndentical*2*ADIO.channels);
              info.SzIndentical=info.SzIndentical*2*ADIO.channels;
            }
            r=indexify(&(_tracks[1+nbAudioTrack]),trackScale,&info,1,&nbo);
            printf("Indexed audio, nb blocks:%u\n",nbo);
            if(r)
            {
                nbo=_tracks[1+nbAudioTrack].nbIndex;
                if(nbo)
                    _tracks[1+nbAudioTrack].nbIndex=nbo;
                else
                    _tracks[1+nbAudioTrack].nbIndex=info.nbSz;
                printf("Indexed audio, nb blocks:%u (final)\n",_tracks[1+nbAudioTrack].nbIndex);
                _tracks[1+nbAudioTrack].scale=trackScale;
                nbAudioTrack++;
            }
            
            break;
    case TRACK_OTHER:
        r=1;
        break;
  }
  return r;
}
Esempio n. 5
0
uint8_t flvHeader::open(char *name)
{
  uint32_t prevLen, type, size, pts,pos=0;
  
  _isvideopresent=0;
  _isaudiopresent=0;
  audioTrack=NULL;
  videoTrack=NULL;
  _filename=ADM_strdup(name);
  _fd=fopen(name,"rb");
  if(!_fd)
  {
    printf("[FLV] Cannot open %s\n",name);
    return 0; 
  }
  // Get size
  uint32_t fileSize=0;
  fseeko(_fd,0,SEEK_END);
  fileSize=ftello(_fd);
  fseeko(_fd,0,SEEK_SET);
  printf("[FLV] file size :%u bytes\n",fileSize);
  // It must begin by F L V 01
  uint8_t four[4];
  
  read(4,four);
  if(four[0]!='F' || four[1]!='L' || four[2]!='V')
  {
     printf("[FLV] Not a flv file %s\n",name);
    return 0; 
  }
  // Next one is flags
  uint32_t flags=read8();
  if(flags & 1) // VIDEO
  {
    _isvideopresent=1;
    printf("[FLV] Video flag\n");
  }else 
    {
    GUI_Info_HIG(ADM_LOG_INFO,"Warning","This FLV file says it has no video.\nI will assume it has and try to continue");
    _isvideopresent=1;
    }   
  if(flags & 4) // Audio
  {
    _isaudiopresent=1;
    printf("[FLV] Audio flag\n");
  }
  
  
  // Skip header
  uint32_t skip=read32();
  fseeko(_fd,skip,SEEK_SET);
  printf("[FLV] Skipping %u header bytes\n",skip);
  
  
  pos=ftello(_fd);;
  printf("pos:%u/%u\n",pos,fileSize); 
  // Create our video index
  videoTrack=new flvTrak(50);
  if(_isaudiopresent) 
    audioTrack=new flvTrak(50);
  else
    audioTrack=NULL;
  // Loop
  while(pos<fileSize-14)
  {
    pos=ftello(_fd);
    prevLen=read32();
    type=read8();
    size=read24();
    pts=read24();
    read32(); // ???
    uint32_t remaining=size;
    //printf("[FLV] At %08x found type %x size %u pts%u\n",pos,type,size,pts);
    switch(type)
    {
      case FLV_TAG_TYPE_AUDIO:
          {
            if(!_isaudiopresent) 
            {
                audioTrack=new flvTrak(50);
                _isaudiopresent=1; /* Damn  lying headers...*/
            };
            uint8_t flags=read8();
            int of=1+4+3+3+1+4;
            remaining--;
            int format=flags>>4;
            int fq=(flags>>2)&3;
            int bps=(flags>>1) & 1;
            int channel=(flags) & 1;
            if(!audioTrack->_nbIndex) // first frame..
            {
               setAudioHeader(format,fq,bps,channel);
            }
            insertAudio(pos+of,remaining,pts);
          }
          break;
      case FLV_TAG_TYPE_VIDEO:
          {
            int of=1+4+3+3+1+4;
            uint8_t flags=read8();
            remaining--;
            int frameType=flags>>4;
            
            int codec=(flags)&0xf;
            
            if(codec==FLV_CODECID_VP6)
            {
              read8(); // 1 byte of extraData
              remaining--;
              of++;
            }
            int first=0;
            if(!videoTrack->_nbIndex) first=1;
            insertVideo(pos+of,remaining,frameType,pts);
            if(first) // first frame..
            {
                if(!setVideoHeader(codec,&remaining)) return 0;
            }
            
          }
           break;
      default: printf("[FLV]At 0x%x, unhandled type %u\n",pos,type);
    }
    Skip(remaining);
  } // while
  
  // Udpate frame count etc..
  printf("[FLV] Found %u frames\n",videoTrack->_nbIndex);
   _videostream.dwLength= _mainaviheader.dwTotalFrames=videoTrack->_nbIndex; 
   // Compute average fps
        float f=_videostream.dwLength;
        uint32_t duration=videoTrack->_index[videoTrack->_nbIndex-1].timeCode;
          
        if(duration) 
              f=1000.*1000.*f/duration;
         else  f=25000;
        _videostream.dwRate=(uint32_t)floor(f);
        _videostream.dwScale=1000;
        _mainaviheader.dwMicroSecPerFrame=ADM_UsecFromFps1000(_videostream.dwRate);
   printf("[FLV] Duration %u ms\n",videoTrack->_index[videoTrack->_nbIndex-1].timeCode);
           
   //
    _videostream.fccType=fourCC::get((uint8_t *)"vids");
    _video_bih.biBitCount=24;
    _videostream.dwInitialFrames= 0;
    _videostream.dwStart= 0;
    videoTrack->_index[0].flags=AVI_KEY_FRAME;
    
    // audio track
    _audioStream=new flvAudio(name,audioTrack,&wavHeader);
  printf("[FLV]FLV successfully read\n");
  
  return 1;
}
bool avs_start(FilterInfo *info, FilterInfo *avisynth_info,
               char *fname, AVS_PIPES *avs_pipes)
{
 DEBUG_PRINTF("avsfilter : avs_start()\n");
 DEBUG_PRINTF("avsfilter : %X %X %s %X\n",
              avs_pipes[PIPE_LOADER_WRITE].hpipe,
              avs_pipes[PIPE_FILTER_WRITE].hpipe,
              fname, info);
 DEBUG_PRINTF("avsfilter : avs_start info : frameIncrement %lu totalDuration %llu\n",
              info->frameIncrement, info->totalDuration);

 ADV_Info aii, aio;
 aii.width = info->width;
 aii.height = info->height;
 aii.nb_frames = info->totalDuration / info->frameIncrement;
 aii.encoding = 1;
 aii.codec = 0;
 aii.fps1000 = ADM_Fps1000FromUs(info->frameIncrement);
 aii.orgFrame = 0;
 DEBUG_PRINTF("avsfilter : send ADV_Info to avsloader [fps1000 = %d, nb_frames = %d]\n", aii.fps1000, aii.nb_frames);
 if (!send_cmd(avs_pipes[PIPE_LOADER_WRITE].hpipe,
                LOAD_AVS_SCRIPT, fname,
                strlen(fname) + sizeof("\0")) ||
      !send_cmd(avs_pipes[PIPE_FILTER_WRITE].hpipe,
                SET_CLIP_PARAMETER, &aii,
                sizeof(aii)))
  {
    DEBUG_PRINTF_RED("avsfilter : cannot set script name or set clip parameters\n");
    deinit_pipes(avs_pipes, CMD_PIPE_NUM);
    return false;
  }

  // get avisynth frame info
  PIPE_MSG_HEADER msg;
  if (!receive_cmd(avs_pipes[PIPE_LOADER_READ].hpipe,
                   &msg) ||
      msg.avs_cmd != SET_CLIP_PARAMETER ||
      !receive_data(avs_pipes[PIPE_LOADER_READ].hpipe,
                    &msg, &aio))
  {
    DEBUG_PRINTF_RED("avsfilter : cannot receive avisynth clip parameters\n");
    deinit_pipes(avs_pipes, CMD_PIPE_NUM);
    return false;
  }

  DEBUG_PRINTF("avsfilter : receive ADV_Info from avsloader [fps1000 = %d, nb_frames = %d]\n", aio.fps1000, aio.nb_frames);
  avisynth_info->width = aio.width;
  avisynth_info->height = aio.height;
  avisynth_info->frameIncrement = ADM_UsecFromFps1000(aio.fps1000);
  avisynth_info->totalDuration = aio.nb_frames * avisynth_info->frameIncrement;

  // correct avisynth_info for span of frames, calculate fps change metrics
/*  float k_fps;
  k_fps = float(avisynth_info->frameIncrement) / float(info->frameIncrement);
  DEBUG_PRINTF("avsfilter : FPS change metrics %f\n", k_fps);
  avisynth_info->nb_frames = int (info->nb_frames * k_fps);
  avisynth_info->orgFrame = int (info->orgFrame * k_fps);
  DEBUG_PRINTF("avsfilter : Calculate new span for avisynth script [%d - %d]\n",
               avisynth_info->orgFrame,avisynth_info->orgFrame + avisynth_info->nb_frames);*/
  return true;
}