Esempio n. 1
0
uint8_t asfHeader::loadVideo(asfChunk *s)
{
  uint32_t w,h,x;
            w=s->read32();
            h=s->read32();
            s->read8();
            x=s->read16();
            _isvideopresent=1;

            memset(&_mainaviheader,0,sizeof(_mainaviheader));
            _mainaviheader.dwWidth=w;
            _mainaviheader.dwHeight=h;
            _video_bih.biWidth=w;
            _video_bih.biHeight=h;
            printf("Pic Width  %04d\n",w);
            printf("Pic Height %04d\n",h);
            printf(" BMP size  %04d (%04d)\n",x,sizeof(BITMAPINFOHEADER));
            s->read((uint8_t *)&_video_bih,sizeof(BITMAPINFOHEADER));
            _videostream.dwScale=1000;
            _videostream.dwRate=30000;

            _videostream.fccHandler=_video_bih.biCompression;
            printf("Codec : <%s> (%04x)\n",
                    fourCC::tostring(_video_bih.biCompression),_video_bih.biCompression);
            if(fourCC::check(_video_bih.biCompression,(uint8_t *)"DVR "))
            {
              // It is MS DVR, fail so that the mpeg2 indexer can take it from here
              _videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t *)"MPEG");
              printf("This is MSDVR, not ASF\n");
              return 0; 
            }
            printBih(&_video_bih);
            if(x>sizeof(BITMAPINFOHEADER))
            {
              _extraDataLen=x-sizeof(BITMAPINFOHEADER);
              _extraData=new uint8_t[_extraDataLen];
              s->read(_extraData,_extraDataLen);
            }
            return 1;
}
void OpenDMLHeader::Dump( void )
{
        printf(  "Main header\n" );
        printf(  "______________________\n" );  

#define X_DUMP(x) printf(#x":\t\t:%ld\n",_mainaviheader.x);
    	X_DUMP(dwStreams);
    	X_DUMP(dwMicroSecPerFrame) ;
	X_DUMP(dwMaxBytesPerSec);
    	X_DUMP(dwPaddingGranularity);
    	X_DUMP(dwFlags);
    	X_DUMP(dwTotalFrames);
    	X_DUMP(dwInitialFrames);	
    	X_DUMP(dwWidth);
    	X_DUMP(dwHeight);
 	printf("\n");
#undef X_DUMP
#define X_DUMP(x) printf("\n "#x":\t\t:%ld",_videostream.x);

				
	printf(  "video stream attached:\n" );
	printf(  "______________________\n" );	
	printf(" Extra Data  : %ld",_videoExtraLen);
	if(_videoExtraLen)
	{
		mixDump( _videoExtraData, _videoExtraLen);
	}

	printf("\n fccType     :");
	fourCC::print(_videostream.fccType);
	printf("\n fccHandler :");
	fourCC::print(_videostream.fccHandler);

	X_DUMP(dwFlags);
	X_DUMP(dwInitialFrames);
	X_DUMP(dwRate);
	X_DUMP(dwStart);
	X_DUMP(dwSampleSize);
	X_DUMP(dwScale);
	X_DUMP(dwLength); 
    	X_DUMP(dwQuality);
	X_DUMP(dwSampleSize);
	printf("\n");
	  	  
        printBih(&_video_bih);

        /*****************************************************************
                Dump infos about all audio tracks found

        ******************************************************************/
        for(int i=0;i<_nbAudioTracks;i++)
     	{
#undef X_DUMP
#define X_DUMP(x) printf("\n "#x":\t\t:%ld",_audioTracks[i].avistream->x);



	   printf(  "\naudio stream attached:\n" );
	   printf(  "______________________\n" );


	  printf("\n fccType     :");
	  fourCC::print(_audioTracks[i].avistream->fccType);
	  printf("\n fccHandler :");
	  fourCC::print(_audioTracks[i].avistream->fccHandler);
	  printf("\n fccHandler :0x%lx", _audioTracks[i].avistream->fccHandler);


	  X_DUMP(dwFlags);
	  X_DUMP(dwInitialFrames);
	  X_DUMP(dwRate);
	  X_DUMP(dwScale);
	  X_DUMP(dwStart);
	  X_DUMP(dwLength);
	  X_DUMP(dwSuggestedBufferSize);
	  X_DUMP(dwQuality);
	  X_DUMP(dwSampleSize);
	  
	      	
	  
#undef X_DUMP

        printWavHeader(_audioTracks[i].wavHeader);
        printf(" Extra Data  : %ld\n",_audioTracks[i].extraDataLen);
	if(_audioTracks[i].extraDataLen)
	{
		mixDump( _audioTracks[i].extraData, _audioTracks[i].extraDataLen);
	}
	printf("\n");

      }
}
uint8_t asfHeader::loadVideo(asfChunk *s)
{
  uint32_t w,h,x;
            printf("--\n");
            w=s->read32();
            h=s->read32();
            s->read8();
            x=s->read16();
            _isvideopresent=1;

            memset(&_mainaviheader,0,sizeof(_mainaviheader));
            _mainaviheader.dwWidth=w;
            _mainaviheader.dwHeight=h;
            _video_bih.biWidth=w;
            _video_bih.biHeight=h;
            printf("Pic Width  %04d\n",w);
            printf("Pic Height %04d\n",h);
            printf(" BMP size  %04d (%04d)\n",x,(int)sizeof(ADM_BITMAPINFOHEADER));
            s->read((uint8_t *)&_video_bih,sizeof(ADM_BITMAPINFOHEADER));

		#ifdef ADM_BIG_ENDIAN
			Endian_BitMapInfo(&_video_bih);
		#endif


            _videostream.fccHandler=_video_bih.biCompression;
            printf("Codec : <%s> (%04x)\n",
                    fourCC::tostring(_video_bih.biCompression),_video_bih.biCompression);
            if(fourCC::check(_video_bih.biCompression,(uint8_t *)"DVR "))
            {
              // It is MS DVR, fail so that the mpeg2 indexer can take it from here
              _videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t *)"MPEG");
              printf("This is MSDVR, not ASF\n");
              return 0; 
            }
            printBih(&_video_bih);
#if 1
            if(_video_bih.biSize>sizeof(ADM_BITMAPINFOHEADER))
            {
                    x=_video_bih.biSize;
#else
            if(x>sizeof(ADM_BITMAPINFOHEADER))
            {
#endif
              _videoExtraLen=x-sizeof(ADM_BITMAPINFOHEADER);
              _videoExtraData=new uint8_t[_videoExtraLen];
              s->read(_videoExtraData,_videoExtraLen);
              ADM_info("We have %d bytes of extra data for video.\n",(int)_videoExtraLen);
            }else
            {
                ADM_info("No extra data for video\n");
            }
            uint64_t l=ftello(_fd);
            printf("Bytes left : %d\n",(int)(s->endPos()-l));
            return 1;
}
/**
    \fn      buildIndex
    \brief   Scan the file to build an index
    
    Header Chunk
            Chunk
            Chunk
            Chunk
            
    Data chunk
            Chunk
            Chunk
            
    We skip the 1st one, and just read the header of the 2nd one
    
*/
uint8_t asfHeader::buildIndex(void)
{
  uint32_t fSize;
  const chunky *id;
  uint32_t chunkFound;
  uint32_t r=5;
  uint32_t len;
  
  fseeko(_fd,0,SEEK_END);
  fSize=ftello(_fd);
  fseeko(_fd,0,SEEK_SET);
  
  asfChunk h(_fd);
  printf("[ASF] ********** Building index **********\n");
  printf("[ASF] Searching data\n");
  while(r--)
  {
    h.nextChunk();    // Skip headers
    id=h.chunkId();
    h.dump();
    if(id->id==ADM_CHUNK_DATA_CHUNK) break;
    h.skipChunk();
  }
  if(id->id!=ADM_CHUNK_DATA_CHUNK) return 0;
  // Remove leftover from DATA_chunk
 // Unknown	GUID	16
//       Number of packets	UINT64	8
//       Unknown	UINT8	1
//       Unknown	UINT8	1
//   
  h.read32();
  h.read32();
  h.read32();
  h.read32();
  _nbPackets=(uint32_t) h.read64();
  h.read16();
  
  len=h.chunkLen-16-8-2-24;
  
  printf("[ASF] nbPacket  : %u\n",_nbPackets);
  printf("[ASF] len to go : %u\n",len);
  printf("[ASF] scanning data\n");
  _dataStartOffset=ftello(_fd);
  
  // Here we go
  asfPacket *aPacket=new asfPacket(_fd,_nbPackets,_packetSize,
                                   &readQueue,&storageQueue,_dataStartOffset);
  uint32_t packet=0;
#define MAXIMAGE (_nbPackets)
  uint32_t sequence=0;
  uint32_t ceilImage=MAXIMAGE;

  nbImage=0;
  
  len=0;
  asfIndex indexEntry;
  memset(&indexEntry,0,sizeof(indexEntry));
  bool first=true;
  DIA_workingBase *progressBar=createWorking("Indexing");
  uint32_t fileSizeMB=(uint32_t)(fSize>>10);

  uint64_t lastDts[ASF_MAX_AUDIO_TRACK];
  for(int i=0;i<ASF_MAX_AUDIO_TRACK;i++)
  {
        lastDts[i]=0;
  }


  while(packet<_nbPackets)
  {
    while(readQueue.size())
    {
      asfBit *bit=NULL;

      // update UI
      uint32_t curPos=(uint32_t)(ftello(_fd)>>10);
      progressBar->update(curPos,fileSizeMB);

      bit=readQueue.front();
      readQueue.pop_front();

      // --
      uint64_t dts=bit->dts;
      uint64_t pts=bit->pts;
        aprintf("** DTS=%s\n",ADM_us2plain(dts));
        aprintf("** PDTS=%s\n",ADM_us2plain(pts));
      if(bit->stream==_videoStreamId)
      {
          aprintf(">found video packet of size=%d off=%d seq %d, while curseq =%d, dts=%s",
                        bit->len,bit->offset,  bit->sequence,curSeq, ADM_us2plain(dts));
          aprintf(" pts=%s\n",ADM_us2plain(pts));
          if(bit->sequence!=sequence || first==true)
          {
            if(first==false)
            {
                indexEntry.frameLen=len;
                aprintf("Pushing video frame index=%d seq=%d pts=%s \n",
                        _index.size(),
                        indexEntry.segNb,ADM_us2plain(indexEntry.pts));
                aprintf("dts=%s\n",ADM_us2plain(indexEntry.dts));
                _index.append(indexEntry);
            }
            
            aprintf("New sequence\n");
            if( ((sequence+1)&0xff)!=(bit->sequence&0xff))
            {
                ADM_warning("!!!!!!!!!!!! non continuous sequence %u %u\n",sequence,bit->sequence); 
            }
            
            
            indexEntry.frameLen=0;
            indexEntry.segNb=bit->sequence;
            indexEntry.packetNb=bit->packet;
            indexEntry.flags=bit->flags;
            indexEntry.dts=dts;
            indexEntry.pts=pts;
            if(first==false)
            {
                sequence=bit->sequence;
                readQueue.push_front(bit); // reuse it next time
                len=0;
                continue;

            }else
            {
                sequence=bit->sequence;
                first=false; // first packet
            }
            
          }
          len+=bit->len;
      } // End of video stream Id
      else  // Audio ?
      {
        int found=0;
        for(int i=0;i<_nbAudioTrack && !found;i++)
        {
          if(bit->stream == _allAudioTracks[i].streamIndex)
          {
            if(bit->pts!=ADM_NO_PTS)
            {
                if(!lastDts[i] || (bit->pts>lastDts[i]+500000L)) // seek point every 500 ms
                {
                    asfAudioSeekPoint seek;
                        seek.pts=bit->pts;
                        seek.packetNb=bit->packet;
                        (audioSeekPoints[i]).append(seek);
      
#if 1
                        if(!lastDts[i])
                            printf("Adding seek point for track %d at %s (packet=%d)\n",
                            i,ADM_us2plain(bit->pts),(int)seek.packetNb);
#endif
                        lastDts[i]=bit->pts;
                        aprintf("Adding seek point for track %d at %s (packet=%d)\n",
                            i,ADM_us2plain(bit->pts),(int)seek.packetNb);
                }
            }
            found=1;
          }
        }
        if(!found) 
        {
          printf("Unmapped stream %u\n",bit->stream); 
        }
      }
      delete [] bit->data;
      bit->data=NULL;
      storageQueue.push_back(bit);
    }
    //working->update(packet,_nbPackets);

    packet++;
    aPacket->nextPacket(0xff); // All packets
    aPacket->skipPacket();
  }
  delete progressBar;
  delete aPacket;
  //delete working;
  /* Compact index */
  
  fseeko(_fd,_dataStartOffset,SEEK_SET);
  printf("[ASF] %u images found\n",nbImage);
  printf("[ASF] ******** End of buildindex *******\n");

  nbImage=_index.size();;
  if(!nbImage) return 0;
  
  uint64_t shift=60*1000*1000;
  bool canShift=false;
  uint64_t tPts;
  tPts=_index[0].pts;
    ADM_info("First image pts: %s, dts: %s\n",ADM_us2plain(tPts), ADM_us2plain(_index[0].dts));
   if(tPts != ADM_NO_PTS)
    {
        shift=tPts;
        ADM_info("Video shift = %s\n",ADM_us2plain(tPts));
        canShift=true;
    }else
        canShift=false;
    for(int i=0;i<_nbAudioTrack;i++)
    {
        if(!audioSeekPoints[i].size())
        {
            ADM_info("audio track : %d, no seek\n",i);
            canShift=false;
            continue;
        }
        tPts=audioSeekPoints[i][0].pts;
        ADM_info("audio track : %d, %s\n",i,ADM_us2plain(tPts));
        if(tPts<shift) shift=tPts;
    }
    if(canShift)
    {
            ADM_info("Shifting a/v raw=%s\n",ADM_us2plain(shift));
    }else
    {
            ADM_info("Can t shift\n");
            shift=0;
    }
  _videostream.dwLength=_mainaviheader.dwTotalFrames=nbImage;
  
  _index[0].flags=AVI_KEY_FRAME;
  if(_index[0].pts==ADM_NO_PTS) _index[0].pts=_index[0].dts;
  // Update fps
  // In fact it is an average fps
  //
    _videostream.dwScale=1000;
    // check if we have a duration per frame for video...
    int n=frameDurationMapping.size();
    int dex=-1;
    for(int i=0;i<n;i++)
    {
        if(frameDurationMapping[i].streamNb==_videoStreamId)
            dex=i;
    }
    if(dex!=-1)
    {
        ADM_info("Average fps provided\n");
        setFps(frameDurationMapping[dex].usPerFrame);
    }
    else
    {
      ADM_info("Fps not provided, guessing it from nbFrame and duration\n");
      uint32_t avgFps;
      if(_index[nbImage-1].pts!=ADM_NO_PTS && _index[0].pts!=ADM_NO_PTS)
      {
          float f=(_index[nbImage-1].pts-_index[0].pts);
            f/=nbImage; // average duration of 1 image in us
            setFps((uint64_t) f);
      }else
        {
            printf("[Asf] No pts, setting 30 fps hardcoded\n");
            _videostream.dwRate=(uint32_t)30000;;
        }
    }
    if(shift)
    {
        double frames3=_videostream.dwScale;
                frames3/=_videostream.dwRate;
                frames3*=3*1000*1000; // 
            ADM_info("3 frames time = %s\n",ADM_us2plain((uint64_t)frames3));
        uint64_t frame64=(uint64_t)frames3;
        if(frame64<shift) shift=shift-frame64;
        else shift=0;

        shiftAudioVideoBy(shift);
    }
    return 1;
  
}