/**
    \fn open

*/
uint8_t    OpenDMLHeader::open(const char *name)
{
uint8_t badAvi=0;
uint32_t rd;

	printf("** opening OpenDML files **");	
        
	_fd=ADM_fopen(name,"rb");
	if(!_fd)
	{
		printf("\n cannot open %s \n",name);
		return 0;
	}
        myName=ADM_strdup(name);
#define CLR(x)              memset(& x,0,sizeof(  x));

          CLR( _videostream);
          CLR( _mainaviheader);
	      _isvideopresent=1;
	      _isaudiopresent=0;    	     	      	 	      
	      
		_nbTrack=0;
		riffParser *parser=new riffParser(name);
		
		if(MKFCC('R','I','F','F')!=(rd=parser->read32()))
			{
				printf("Not riff\n");badAvi=1;
				printf("%x != %x\n",rd,MKFCC('R','I','F','F'));
			}
		parser->read32();
		if(MKFCC('A','V','I',' ')!=parser->read32())
			{
				printf("Not Avi\n");badAvi=1;
			}
		
		if(!badAvi)
			{
				walk(parser);	
			
			}					
		delete parser;
		aprintf("Found %d tracks\n:-----------\n",_nbTrack);
		// check if it looks like a correct avi
		if(!_nbTrack) badAvi=1;
		
		// if we are up to here -> good avi :)
		if(badAvi)
		{
			printf("FAIL\n");
			return 0;
		}
		// now read up each parts...
		//____________________________
		                
#define DUMP_TRACK(i) aprintf(" at %"PRIu64" (%"PRIx64") size : %"PRIu64" (%"PRIx64")\n", \
				_Tracks[i].strh.offset,\
				_Tracks[i].strh.offset,\
				_Tracks[i].strh.size,\
				_Tracks[i].strh.size);

		for(uint32_t i=0;i<_nbTrack;i++)
		{
			DUMP_TRACK(i);		
		}		
		
		uint32_t vidTrack=0xff;
		// search wich track is the video one
		// and load it to _videoheader
		
		for(uint32_t i=0;i<_nbTrack;i++)
		{
			fseeko(_fd,_Tracks[i].strh.offset,SEEK_SET);
			if(_Tracks[i].strh.size!=sizeof(_videostream))
			{
				printf("[AVI]Mmm(1) we have a bogey here, size mismatch : %"PRIu64"\n",_Tracks[i].strh.size);
				printf("[AVI]expected %d\n",(int)sizeof(_videostream));
				if(_Tracks[i].strh.size<sizeof(_videostream)-8) // RECT is not mandatory
				{
                                  GUI_Error_HIG(QT_TR_NOOP("Malformed header"), NULL);
					return 0;
				}		
				printf("[AVI]Trying to continue anyway\n");			
			}
			fread(&_videostream,sizeof(_videostream),1,_fd);
#ifdef ADM_BIG_ENDIAN
				Endian_AviStreamHeader(&_videostream);
#endif
			if(_videostream.fccType==MKFCC('v','i','d','s'))
				{
					vidTrack=i;
					printf("Video track is %u\n",i);
					break;
				}		
		}
		if(0xff==vidTrack)
		{
			printf("Could not identify video track!");
			return 0;
		}
		
		// then bih stuff
		int32_t extra;
//		_fd=fopen(name,"rb");
		
		fseeko(_fd,_Tracks[vidTrack].strf.offset,SEEK_SET);		
		extra=_Tracks[vidTrack].strf.size-sizeof(_video_bih);
		if(extra<0)
		{	
			printf("[AVI]bih is not big enough (%"PRIu64"/%d)!\n",_Tracks[vidTrack].strf.size,(int)sizeof(_video_bih));
			return 0;
		}
		fread(&_video_bih,sizeof(_video_bih),1,_fd);
#ifdef ADM_BIG_ENDIAN
		Endian_BitMapInfo(&_video_bih);
#endif
		if(extra>0)
		{				
			_videoExtraLen=extra;		
			_videoExtraData=new uint8_t [extra];
			fread(_videoExtraData,extra,1,_fd);
		}
		_isvideopresent=1;
		//--------------------------------------------------
		//	Read audio trak info, select if there is
		//	several
		//--------------------------------------------------
		// and audio track
		if(_mainaviheader.dwStreams>=2)
		{
			// which one is the audio track, is there several ?
			if(!(_nbAudioTracks=countAudioTrack()))
                        {
                                printf("Weird, there is no audio track, but more than one stream...\n");
                        }			
                        else
                        {
                          uint32_t run=0,audio=0;
                          odmlAudioTrack *track;

                          _audioTracks=new odmlAudioTrack[_nbAudioTracks]; 
                          _audioStreams=new ADM_audioStream *[_nbAudioTracks]; 
                          while(audio<_nbAudioTracks)
                          {
                                        ADM_assert(run<_nbTrack);

                                        track=&(_audioTracks[audio]);
                                        fseeko(_fd,_Tracks[run].strh.offset,SEEK_SET);
                                        if(_Tracks[run].strh.size != sizeof(_audiostream))
                                        {
                                                printf("[AVI]Mmm(2) we have a bogey here, size mismatch : %"PRIu64"\n",_Tracks[run].strh.size);
                                                printf("[AVI]expected %d\n",(int)sizeof(_audiostream));
                                                if(_Tracks[run].strh.size<sizeof(_audiostream)-8)
                                                {
                                                  GUI_Error_HIG(QT_TR_NOOP("Malformed header"), NULL);
                                                        return 0;
                                                }
                                                printf("[AVI]Trying to continue anyway\n");			
                                        }
                                        fread(track->avistream,sizeof(_audiostream),1,_fd);
#ifdef ADM_BIG_ENDIAN
                                        Endian_AviStreamHeader(track->avistream);
#endif
                                        if(track->avistream->fccType!=MKFCC('a','u','d','s'))
                                        {	
                                                printf("Not an audio track!\n");
                                                run++;
                                                continue;
                                        }
                                        // now read extra stuff
                                        fseeko(_fd,_Tracks[run].strf.offset,SEEK_SET);		
                                        extra=_Tracks[run].strf.size-sizeof(WAVHeader);
                                        if(extra<0)
                                        {	
                                                printf("[AVI]WavHeader is not big enough (%"PRIu64"/%d)!\n",
                                                _Tracks[run].strf.size,(int)sizeof(WAVHeader));
                                                return 0;
                                        }
                                        fread(track->wavHeader,sizeof(WAVHeader),1,_fd);				
#ifdef ADM_BIG_ENDIAN
                                        Endian_WavHeader(track->wavHeader);
#endif
                                        if(extra>2)
                                        {
                                                fgetc(_fd);fgetc(_fd);
                                                extra-=2;
                                                track->extraDataLen=extra;		
                                                track->extraData=new uint8_t [extra];
                                                fread(track->extraData,extra,1,_fd);
                                        }
                                        track->trackNum=run;
                                        audio++;
                                        run++;
                           }	
                        }
                }
		
		// now look at the index stuff
		// there could be 3 cases:
		// 1- It is a openDML index, meta index  + several smaller index
		// 2- It is a legacy index (type 1 , most common)
		// 3- It is a broken index or no index at all
		//
		// If it is a openDML index we will find a "indx" field in the Tracks
		// Else we will find it in _regularIndex Track
		// Since openDML often also have a regular index we will try open DML first
		
		uint8_t ret=0;
		Dump();
		
		// take the size of riff header and actual file size
		uint64_t riffSize;
		fseeko(_fd,0,SEEK_END);		
		_fileSize=ftello(_fd);
		fseeko(_fd,0,SEEK_SET);
		read32();
		riffSize=(uint64_t )read32();
				
		
		// 1st case, we have an avi < 4 Gb
		// potentially avi type 1	
#if 0	
		if((_fileSize<4*1024*1024*1024LL)&&
                	// if riff size is ~ fileSize try regular index
			 (abs(riffSize-_fileSize)<1024*1024))
#endif

#define HAS(x) if(x) printf(#x" : yes\n"); else printf(#x" : no\n");
                // If there is no openDML index
                HAS( _regularIndex.offset);
                HAS( _Tracks[vidTrack].indx.offset);
                if(!ret && _regularIndex.offset &&!_Tracks[vidTrack].indx.offset) 
        // try regular avi if a idx1 field is there (avi index)
                        ret=indexRegular(vidTrack);

                if (!ret && _Tracks[vidTrack].indx.offset)	// Try openDML if a index field is there (openDML)
                        ret=indexODML(vidTrack);
                if(!ret) 
                {
                        printf("Could not index it properly...\n");
                        return 0;

                }
                if(!_nbAudioTracks)
                {
                         _isaudiopresent=0;
                }
                else
                {
                        odmlAudioTrack *track;
                        // Check it is not a weird DV file
                        if(fourCC::check(_video_bih.biCompression,(uint8_t *)"dvsd"))
                        {
                             for(int i=0;i<_nbAudioTracks;i++)
                             {
                                    track=&(_audioTracks[i]);
                                    WAVHeader *hdr=  track->wavHeader;
                                    if(!hdr->frequency)
                                    {
                                            ADM_warning("Fixing audio track to be PCM\n");
                                            hdr->frequency=48000;
                                            //hdr->channels=2;
                                            hdr->byterate=48000*hdr->channels*2;
                                            hdr->blockalign=2*hdr->channels;
                                    }
                             }

                        }
                        // build audio stream
                        
                        for(int i=0;i<_nbAudioTracks;i++)
                        {
                                track=&(_audioTracks[i]);
                                ADM_aviAudioAccess *access=new ADM_aviAudioAccess(track->index,track->wavHeader,
                                            track->nbChunks,
                                            myName,
                                            track->extraDataLen,track->extraData);
                                _audioStreams[i]= ADM_audioCreateStream((track->wavHeader), access);
                        }
                }
                if(!_video_bih.biCompression && fourCC::check(_videostream.fccHandler,(uint8_t*)"DIB "))
                  {
                        _videostream.fccHandler=_video_bih.biCompression=fourCC::get((uint8_t*)"DIB ");
                  }
                else
                _videostream.fccHandler=_video_bih.biCompression;
                printf("\nOpenDML file successfully read..\n");
                if(ret==1) 
                {
                    computePtsDts();
                    removeEmptyFrames();
                }
                ADM_info("PtsAvailable : %d\n",(int)ptsAvailable);
                return ret;
}
//___________________________________________________
uint8_t	ADM_ogmWrite::writeVideo(uint32_t frame)
{
		ADM_assert(0);
		return 0;

}
uint8_t lavMuxer::open(const char *filename,uint32_t inbitrate, ADM_MUXER_TYPE type, aviInfo *info,
              uint32_t videoExtraDataSize, uint8_t *videoExtraData, WAVHeader *audioheader,
              uint32_t audioextraSize,uint8_t *audioextraData)
{
 AVCodecContext *c;
 	_type=type;
	_fps1000=info->fps1000;
	switch(_type)
	{
	case MUXER_TS:
		fmt=guess_format("mpegts", NULL, NULL);
		break;
	case MUXER_DVD:
		fmt = guess_format("dvd", NULL, NULL);
		break;
	case MUXER_VCD:
		fmt = guess_format("vcd", NULL, NULL);
		break;
	case MUXER_SVCD:
		fmt = guess_format("svcd", NULL, NULL);
		break;
	case MUXER_MP4:
		fmt = guess_format("mp4", NULL, NULL);
		break;
	case MUXER_PSP:
		fmt = guess_format("psp", NULL, NULL);
		break;
	case MUXER_FLV:
		fmt = guess_format("flv", NULL, NULL);
		break;          
	case MUXER_MATROSKA:
		fmt = guess_format("matroska", NULL, NULL);
		break;          

	default:
		fmt=NULL;
	}
	if (!fmt) 
	{
        	printf("Lav:Cannot guess format\n");
                ADM_assert(0);
		return 0;
	}
	oc = av_alloc_format_context();
	if (!oc) 
	{
       		printf("Lav:Cannot allocate context\n");
		return 0;
	}
	oc->oformat = fmt;
	snprintf(oc->filename,1000,"file://%s",filename);
	// Video
	//________
	
	video_st = av_new_stream(oc, 0);
	if (!video_st) 
	{
		printf("Lav: new stream failed\n");
		return 0;
	}	
	
	c = video_st->codec;
	switch(_type)
	{
				case MUXER_FLV:
					 c->codec=new AVCodec;
					 memset(c->codec,0,sizeof(AVCodec));
					 if(fourCC::check(info->fcc,(uint8_t *)"FLV1"))
					 {
						 c->codec_id=CODEC_ID_FLV1;
					 	 c->codec->name=ADM_strdup("FLV1");
					 }else
					 {
						 if(fourCC::check(info->fcc,(uint8_t *)"VP6F"))
						 			{
							 		 c->codec_id=CODEC_ID_VP6F;
					 				 c->codec->name=ADM_strdup("VP6F");
						 			}
						 else
							 ADM_assert(0);
					 
					 }
					 
					 break;
                case MUXER_MATROSKA:
                        strcpy(oc->title,"Avidemux");
                        strcpy(oc->author,"Avidemux");
                        c->sample_aspect_ratio.num=1;
                        c->sample_aspect_ratio.den=1;
                        if(isMpeg4Compatible(info->fcc))
                        {
                                c->codec_id = CODEC_ID_MPEG4;
                                c->has_b_frames=1; // in doubt...
                        }else
                        {
                                if(isH264Compatible(info->fcc))
                                {
                                        c->has_b_frames=1; // in doubt...
                                        c->codec_id = CODEC_ID_H264;
                                        c->codec=new AVCodec;
                                        memset(c->codec,0,sizeof(AVCodec));
                                        c->codec->name=ADM_strdup("H264");
                                }
                                else
                                {
                                   if(!ADM_4cc_to_lavcodec((const char *)&(info->fcc),&(c->codec_id)))
                                   {
                                      printf("[lavFormat] Cannot map  this\n");
                                      return 0;
                                   }
                                  
                                }
                        }
                        if(videoExtraDataSize)
                        {
                                c->extradata=videoExtraData;
                                c->extradata_size= videoExtraDataSize;
                        }
                        break;
                case MUXER_MP4:
                case MUXER_PSP:
                {
                        // probably a memeleak here
                        char *foo=ADM_strdup(filename);
                        
                        strcpy(oc->title,ADM_GetFileName(foo));
                        strcpy(oc->author,"Avidemux");
                        c->sample_aspect_ratio.num=1;
                        c->sample_aspect_ratio.den=1;
                        if(isMpeg4Compatible(info->fcc))
                        {
                                c->codec_id = CODEC_ID_MPEG4;
                                c->has_b_frames=1; // in doubt...
                        }else
                        {
                                if(isH264Compatible(info->fcc))
                                {
                                        c->has_b_frames=1; // in doubt...
                                        c->codec_id = CODEC_ID_H264;
                                        c->codec=new AVCodec;
                                        memset(c->codec,0,sizeof(AVCodec));
                                        c->codec->name=ADM_strdup("H264");
                                }
                                else
                                {
                                        if(isDVCompatible(info->fcc))
                                        {
                                          c->codec_id = CODEC_ID_DVVIDEO;
                                        }else
                                        {
                                          if(fourCC::check(info->fcc,(uint8_t *)"H263"))
                                          {
                                                    c->codec_id=CODEC_ID_H263;
                                            }else{
                                                    c->codec_id = CODEC_ID_MPEG4; // Default value
                                                    printf("Ooops, cant mux that...\n");
                                                    printf("Ooops, cant mux that...\n");
                                                    printf("Ooops, cant mux that...\n");
                                                }
                                        }
                                }
                        }
                        if(videoExtraDataSize)
                        {
                                c->extradata=videoExtraData;
                                c->extradata_size= videoExtraDataSize;
                        }
                        if(MUXER_PSP==_type)
                        {
                            c->rc_buffer_size=0; //8*1024*224;
                            c->rc_max_rate=0; //768*1000;
                            c->rc_min_rate=0;
                            c->bit_rate=768*1000;
                        }
                        else
                        {
                            c->rc_buffer_size=8*1024*224;
                            c->rc_max_rate=9500*1000;
                            c->rc_min_rate=0;
                            if(!inbitrate)
                                    c->bit_rate=9000*1000;
                            else
                                    c->bit_rate=inbitrate;
                        }
                }
                        break;
                case MUXER_TS:
                        c->codec_id = CODEC_ID_MPEG2VIDEO;
                        c->rc_buffer_size=8*1024*224;
                        c->rc_max_rate=9500*1000;
                        c->rc_min_rate=0;
                        if(!inbitrate)
                                c->bit_rate=9000*1000;
                        else
                                c->bit_rate=inbitrate;
        
                        break;
		case MUXER_DVD:
			c->codec_id = CODEC_ID_MPEG2VIDEO;
			c->rc_buffer_size=8*1024*224;
			c->rc_max_rate=9500*1000;
			c->rc_min_rate=0;
			if(!inbitrate)
				c->bit_rate=9000*1000;
			else
				c->bit_rate=inbitrate;
	
			break;
		case MUXER_VCD:
			c->codec_id = CODEC_ID_MPEG1VIDEO;

			c->rc_buffer_size=8*1024*40;
			c->rc_max_rate=1152*1000;
			c->rc_min_rate=1152*1000;
			
			c->bit_rate=1152*1000;
			

			break;
		case MUXER_SVCD:
			c->codec_id = CODEC_ID_MPEG2VIDEO;

			c->rc_buffer_size=8*1024*112;
			c->rc_max_rate=2500*1000;
			c->rc_min_rate=0*1000;
			if(!inbitrate)
				c->bit_rate=2040*1000;
			else
				c->bit_rate=inbitrate;

			break;
		default:
			ADM_assert(0);
	}
	
	c->codec_type = CODEC_TYPE_VIDEO;
	c->flags=CODEC_FLAG_QSCALE;   
	c->width = info->width;  
	c->height = info->height; 

       AVRational fps25=(AVRational){1001,25025};
       AVRational fps24=(AVRational){1001,24000};
       AVRational fps30= (AVRational){1001,30000};
       AVRational fpsfree= (AVRational){1000,_fps1000};

        
    	switch(_fps1000)
	{
		case 25000:
                {
			 c->time_base= fps25; 
			 break;
                }
		case 23976:
                        if(_type==MUXER_MP4 || _type==MUXER_PSP || _type==MUXER_FLV || _type==MUXER_MATROSKA)
                        {
                                 c->time_base= fps24; //(AVRational){1001,24000};
                                break;
                        }
		case  29970:
			 c->time_base=fps30;
			break;
		default:
                      {
                            if(_type==MUXER_MP4 || _type==MUXER_PSP || _type==MUXER_FLV || _type==MUXER_MATROSKA)
                            {
                                    c->time_base=fpsfree;// (AVRational){1000,_fps1000};
                                    break;
                            }
                            else
                            {
                                GUI_Error_HIG(QT_TR_NOOP("Incompatible frame rate"), NULL);
                                return 0;
                            }
                            }
                        break;
	}

			
	c->gop_size=15;
	c->max_b_frames=2;
	c->has_b_frames=1;

	
	// Audio
	//________
        if(audioheader)
        {
          audio_st = av_new_stream(oc, 1);
          if (!audio_st) 
          {
                  printf("Lav: new stream failed\n");
                  return 0;
          }
  
                  
          c = audio_st->codec;
          c->frame_size=1024; //For AAC mainly, sample per frame
          printf("[LavFormat] Bitrate %u\n",(audioheader->byterate*8)/1000);
          _audioFq=c->sample_rate = audioheader->frequency;
#if 0
           if(_type== MUXER_PSP && audioheader->encoding==WAV_AAC)
            {
                    _audioFq=c->sample_rate = audioheader->frequency/2;                 //_audioFq*=2; // SBR
             }
#endif
          
          switch(audioheader->encoding)
          {
                  case WAV_AC3: c->codec_id = CODEC_ID_AC3;break;
                  case WAV_MP2: c->codec_id = CODEC_ID_MP2;break;
                  case WAV_MP3:
  #warning FIXME : Probe deeper
                              c->frame_size=1152;
                              c->codec_id = CODEC_ID_MP3;
                              break;
                  case WAV_PCM: 
                                  // One chunk is 10 ms (1/100 of fq)
                                  c->frame_size=4;
                                  c->codec_id = CODEC_ID_PCM_S16LE;break;
                  case WAV_AAC: 
                                  c->extradata=audioextraData;
                                  c->extradata_size= audioextraSize;
                                  c->codec_id = CODEC_ID_AAC;
                                  break;
                  default:
                          if(_type==MUXER_MATROSKA)
                          {
                           if(ADM_WaveTag_to_lavcodec(audioheader->encoding, &(c->codec_id)))
                           {
                             if(audioextraData)
                             {
                                  c->extradata=audioextraData;
                                  c->extradata_size= audioextraSize;
                             }
                             // Put a dummy time increment
                              c->time_base= fps25;
                             break;
                           }
                          }
                            
                          printf("Cant mux that ! audio\n"); 
                          printf("Cant mux that ! audio\n");
                          c->codec_id = CODEC_ID_MP2;
                          return 0;
                          break;
          }
          c->codec_type = CODEC_TYPE_AUDIO;
          
          c->bit_rate = audioheader->byterate*8;
          c->rc_buffer_size=(c->bit_rate/(2*8)); // 500 ms worth
          
          c->channels = audioheader->channels;
          _audioByterate=audioheader->byterate;
          
        }
        // /audio
	
	
//----------------------
	switch(_type)
	{
				case MUXER_FLV:
                case MUXER_PSP:
                case MUXER_MP4:
                case MUXER_MATROSKA:
                        oc->mux_rate=10080*1000; // Needed ?
                        break;

                case MUXER_TS:
                        oc->mux_rate=10080*1000;
                        break;
		case MUXER_DVD:
			oc->packet_size=2048;
			oc->mux_rate=10080*1000;
			break;
		case MUXER_VCD:
			oc->packet_size=2324;
			oc->mux_rate=2352 * 75 * 8;
			
			break;
		case MUXER_SVCD:
			
			oc->packet_size=2324;
			oc->mux_rate=2*2352 * 75 * 8; // ?
			
			break;
		default:
			ADM_assert(0);
	}
	oc->preload=AV_TIME_BASE/10; // 100 ms preloading
	oc->max_delay=200*1000; // 500 ms
	
	if (av_set_parameters(oc, NULL) < 0) 
	{
		printf("Lav: set param failed \n");
		return 0;
	}
	 if (url_fopen(&(oc->pb), filename, URL_WRONLY) < 0) 
	 {
	 	printf("Lav: Failed to open file :%s\n",filename);
		return 0;
        }

	ADM_assert(av_write_header(oc)>=0);
	dump_format(oc, 0, filename, 1);


	printf("lavformat mpeg muxer initialized\n");
	
	_running=1;

	one=(1000*1000*1000)/_fps1000; 
	_curDTS=one;

	return 1;
}
//--------------------------------
uint8_t EncoderFFMPEG::configure (AVDMGenericVideoStream * instream, int useExistingLogFile)
{

  ADM_assert (instream);
  ADV_Info *
    info;

  uint32_t
    flag1,
    flag2,
    flag3;
  flag1 = flag2 = flag3 = 0;

  info = instream->getInfo ();
  _fps = info->fps1000;
  _w = info->width;
  _h = info->height;

  _vbuffer = new ADMImage (_w, _h);
  ADM_assert (_vbuffer);
  _in = instream;


  switch (_param.mode)
    {
    case COMPRESS_SAME:
      printf ("FFmpeg in follow quant mode\n");
      _state = enc_Same;
      _codec = new ffmpegEncoderVBRExternal (_w, _h, _id);
      _codec->setConfig (&_settings);
      _codec->init (2, _fps, 0);
      break;

    case COMPRESS_CQ:
      printf ("ffmpeg cq mode: %ld\n", _param.qz);
      _state = enc_CQ;
      _codec = new ffmpegEncoderCQ (_w, _h, _id);
      _codec->setConfig (&_settings);
      _codec->init (_param.qz, _fps, 0);
      break;
    case COMPRESS_CBR:
      printf ("ffmpeg cbr mode: %ld\n", _param.bitrate);
      _state = enc_CBR;
      _codec = new ffmpegEncoderCBR (_w, _h, _id);
      _codec->setConfig (&_settings);
      _codec->init (_param.bitrate, _fps, flag1);
      break;
    case COMPRESS_2PASS:
    case COMPRESS_2PASS_BITRATE:
      ffmpegEncoderCQ * cdec;
      if(_param.mode==COMPRESS_2PASS)
        printf ("\n ffmpeg dual size: %lu", _param.finalsize);
      else
        printf ("\n ffmpeg dual bitrate: %lu", _param.avg_bitrate);
      _state = enc_Pass1;
      cdec = new ffmpegEncoderCQ (_w, _h, _id);	// Pass1
      cdec->setConfig (&_settings);
      // 1+  VBR stats required
      // no stats
      // force internal
      cdec->setLogFile (_logname);
      cdec->init (2, _fps, 1);

      _codec = cdec;
      if (flag1)
	_internal = 0;
      else
	_internal = 1;
      break;

      break;
    default:
      ADM_assert (0);

    }
  _in = instream;
  printf ("\n ffmpeg Encoder , w: %lu h:%lu mode:%d", _w, _h, _state);
  return 1;

}
uint8_t         dmx_demuxerTS::sync( uint8_t *stream,uint64_t *abs,uint64_t *r,uint64_t *pts,uint64_t *dts)
{
uint32_t val,hnt;
retry:
         *r=0;

                val=0;
                hnt=0;

                // preload
                hnt=(read8i()<<16) + (read8i()<<8) +read8i();
                if(_lastErr)
                {
                        _lastErr=0;
                        printf("\n io error , aborting sync\n");
                        return 0;       
                }

                while((hnt!=0x00001))
                {

                        hnt<<=8;
                        val=read8i();
                        hnt+=val;
                        hnt&=0xffffff;
 
                        if(_lastErr)
                        {
                             _lastErr=0;
                            printf("\n io error , aborting sync\n");
                            return 0;
                         }

                }

                *stream=read8i();
                // Case 1 : assume we are still in the same packet
                if(_pesBufferIndex>=4)
                {
                        *abs=_pesBufferStart;
                        *r=_pesBufferIndex-4;
                        *pts=_pesPTS;
                        *dts=_pesDTS;
                }
                else
                {       // pick what is needed from oldPesStart etc...
                        // since the beginning in the previous packet
                        uint32_t left=4-_pesBufferIndex;
                                 if(left>_oldPesLen)
                                 { // previous Packet which len is very shoty
                                   // Ignore
                                   _pesBufferIndex=0;
                                   printf("Ignoring too short packet");
                                   goto retry;
                                 }
                                 left=_oldPesLen-left;
#if 0
                                 printf("Next packet : %I64X Len :%lu, using previous packet %I64X len:%u as pos=%lu\n",
                                 		_pesBufferStart,_pesBufferLen,_oldPesStart,_oldPesLen,_pesBufferIndex);
#endif
                                 if(left>_oldPesLen)
                                {
                                        printf("Need %lu bytes from previous packet, which len is %lu\n",left,_oldPesLen);
                                        ADM_assert(0);
                                }
                                *abs=_oldPesStart;
                                *r=left;
                                *pts=_oldPTS;
                                *dts=_oldDTS;
                }
                return 1;
}
void GUI_FileSelWrite(const char *label,char * * name) 
{
	ADM_assert(fileSelDescriptor);
	return fileSelDescriptor->fileWriteName(label,name);	
}
//________________________________________________
//   Init lame encoder
// frequence    : Impose frequency , 0 means reuse the incoming fq
// mode                         : ADM_STEREO etc...
// bitrate              : Bitrate in kbps (96,192...)
// return 0 : init failed
//                              1 : init succeeded
//_______________________________________________
uint8_t AUDMEncoder_Twolame::init(ADM_audioEncoderDescriptor *config)
{
  int ret;
  TWOLAME_MPEG_mode mmode;    	
  uint32_t frequence;
  TWOLAME_encoderParam *lameConf=(TWOLAME_encoderParam *)config->param;
  ADM_assert(config->paramSize==sizeof(TWOLAME_encoderParam));

  _twolameOptions = twolame_init();
  if (_twolameOptions == NULL)
    return 0;
      
  if(_wavheader->channels>2)
  {
    printf("[TwoLame]Too many channels\n");
    return 0; 
  }
  _wavheader->byterate=(config->bitrate*1000)>>3;         
      
 
  _chunk = 1152*_wavheader->channels;

 
  printf("[TwoLame]Incoming :fq : %lu, channel : %lu bitrate: %lu \n",
        _wavheader->frequency,_wavheader->channels,config->bitrate);
		
 
  twolame_set_in_samplerate(OPTIONS, _wavheader->frequency);
  twolame_set_out_samplerate (OPTIONS, _wavheader->frequency);
  twolame_set_num_channels(OPTIONS, _wavheader->channels);
  if(_wavheader->channels==1) mmode=TWOLAME_MONO;
  else
    switch (lameConf->mode)
  {
    case ADM_STEREO:
      mmode = TWOLAME_STEREO;
      break;
    case ADM_JSTEREO:
      mmode = TWOLAME_JOINT_STEREO;
      break;
    case ADM_MONO:
      mmode=TWOLAME_MONO;
      break;
				
    default:
      printf("\n **** unknown mode, going stereo ***\n");
      mmode = TWOLAME_STEREO;
      break;

  }
  twolame_set_mode(OPTIONS,mmode);
  twolame_set_error_protection(OPTIONS,TRUE);	
    	//toolame_setPadding (options,TRUE);
  twolame_set_bitrate (OPTIONS,config->bitrate);
  twolame_set_verbosity(OPTIONS, 2);
  if(twolame_init_params(OPTIONS))
  {
    printf("[TwoLame]Twolame init failed\n");
    return 0;
  }
	
 

  printf("[TwoLame]Libtoolame successfully initialized\n");
  return 1;       
}
//*************************************
void update( void )
{
uint32_t audioSize;
uint32_t totalSize;
char string[200];
aviInfo info;

        video_body->getVideoInfo(&info);

	track1=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(GW(spinbuttonTrack1)));
	track2=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(GW(spinbuttonTrack2)));
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(GW(spinbuttonTrack1)), track1);
	gtk_spin_button_set_value(GTK_SPIN_BUTTON(GW(spinbuttonTrack2)), track1);

	// kb->Byte
	audioSize=(track1+track2)*1000;
	audioSize/=8;

	audioSize*=videoDuration;
	audioSize>>=20;
	sprintf(string,"%"PRIu32,audioSize);
	gtk_label_set_text(GTK_LABEL(GW(labelAudio)),string);

	// Compute total size (for Avi)
	uint32_t s74,s80,dvd;

	// For avi/ogm
	int f = gtk_combo_box_get_active(GTK_COMBO_BOX(GW(comboboxFormat)));
	if(f==2)
	{ // Mpeg
		s74=730;
		s80=790;
		dvd=4300;

	}
	else
	{//AVI or OGM
		s74=650;
		s80=700;
		dvd=4300;
	}

	int j=gtk_combo_box_get_active(GTK_COMBO_BOX(GW(comboboxMedium)));
	switch(j)
	{
		case 2: totalSize=1*s74;break;
		case 3: totalSize=2*s74;break;
		case 0: totalSize=1*s80;break;
		case 1: totalSize=2*s80;break;
		case 4: totalSize=dvd;break;
		case 5: totalSize=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(GW(spinbuttonCustom))); 
		        if(totalSize<1) totalSize=1;
				break;
		default:
			ADM_assert(0);
	}
	sprintf(string,"%"PRIu32,totalSize);
	gtk_label_set_text(GTK_LABEL(GW(labelTotal)),string);

	// Compute muxing overhead size
	uint32_t muxingOverheadSize;
	int numberOfAudioTracks = 0;
	int numberOfChunks;
	switch (f)
	{
		case 0:
			// AVI
			/*
				Muxing overhead is 8 + 32 = 40 bytes per chunk.
				More or less: numberOfChunks = (x + 1) * numberOfVideoFrames,
				where x - the number of audio tracks
			*/
			if (track1 != 0)
			{
				numberOfAudioTracks++;
			}
			if (track2 != 0)
			{
				numberOfAudioTracks++;
			}
			numberOfChunks = (numberOfAudioTracks + 1) * numberOfVideoFrames;
			muxingOverheadSize = (uint32_t) ceil((numberOfChunks * 40) / 1048576.0);;
			break;
		case 1:
			// OGM
			// Muxing overhead is 1.1% to 1.2% of (videoSize + audioSize)
			muxingOverheadSize = (uint32_t) ceil(totalSize - totalSize / 1.012);
			break;
		case 2:
			// MPEG
			// Muxing overhead is 1%  to 2% of (videoSize + audioSize)
			muxingOverheadSize = (uint32_t) ceil(totalSize - totalSize / 1.02);
			break;
		default:
			ADM_assert(0);
	}
	//sprintf(string,"%lu",muxingOverheadSize);
	//gtk_label_set_text(GTK_LABEL(GW(labelMux)),string);

	// and compute
	//
	//uint32_t videoSize;

	if(audioSize>=totalSize) sprintf(string,"** NO ROOM LEFT**");
	else
		{
                        uint32_t picSize;
			videoSize=totalSize-audioSize - muxingOverheadSize;
			// Compute average bps
			float avg;
                        float bpp;
			avg=videoSize;
			avg*=1024.*1024.;
			avg/=videoDuration;
			// now we have byte /sec
			// convert to kb per sec
			avg=(avg*8)/1000;
			videoBitrate=(uint32_t)avg;
			sprintf(string,"%"PRIu32,(uint32_t)videoBitrate);

			gtk_label_set_text(GTK_LABEL(GW(labelBitrate)),string);

			//
			sprintf(string,"%"PRIu32,videoSize);
	                gtk_label_set_text(GTK_LABEL(GW(labelVideo)),string);
                        // Bpp
                        bpp=videoBitrate;
                        bpp=bpp*1000000.;  // kbit->bit + compensate for fps1000
                        // Fetch info from filter


                        if(videoProcessMode())
                                picSize=getPicSize();
                        else
                                picSize=info.width*info.height;
                        bpp/=picSize;
                        //printf("w:%d h:%d\n",info.width,info.height);
                        bpp/=info.fps1000;
                        sprintf(string,"%1.3f",bpp);
                        gtk_label_set_text(GTK_LABEL(GW(labelBPP)),string);

		}



}
/**
        \fn decodeSEI
        \brief decode SEI to get short ref I
        @param recoveryLength # of recovery frame
        \return true if recovery found
*/
bool TsIndexer::decodeSEI(uint32_t nalSize, uint8_t *org,uint32_t *recoveryLength,
                pictureStructure *picStruct)
{
    
    
    ADM_assert(nalSize+16<ADM_NAL_BUFFER_SIZE)
    uint8_t *payload=payloadBuffer;
    bool r=false;
    nalSize=ADM_unescapeH264(nalSize,org,payload);
    uint8_t *tail=payload+nalSize;
    *picStruct=pictureFrame; // frame
    while( payload<tail-2)
    {
                uint32_t sei_type=0,sei_size=0;
                while(payload[0]==0xff) {sei_type+=0xff;payload++;};
                sei_type+=payload[0];payload++;
                while(payload[0]==0xff) {sei_size+=0xff;payload++;};
                sei_size+=payload[0];payload++;
                aprintf("  [SEI] Type : 0x%x size:%d\n",sei_type,sei_size);
                switch(sei_type) // Recovery point
                {

                       case 1:
                            {
                                if(spsInfo.hasStructInfo)
                                {
                                    getBits bits(sei_size,payload);
                                    payload+=sei_size;
                                    if(spsInfo.CpbDpbToSkip)
                                    {
                                            bits.get(spsInfo.CpbDpbToSkip);
                                    }
                                    //printf("Consumed: %d,\n",bits.getConsumedBits());
                                    int pic=bits.get(4);
                                    aprintf("Pic struct: %d,\n",pic);
                                    switch(pic) 
                                    {
                                        case 0: *picStruct=pictureFrame; break;
                                        case 3:
                                        case 4: *picStruct=pictureFrame;
                                        case 1: *picStruct=pictureTopField;break;
                                        case 2: *picStruct=pictureBottomField;break;
                                        default:*picStruct=pictureFrame;
                                    }
                                    
                                }else
                                        payload+=sei_size;
                            }
                            break;

                       case 6:
                        {
                            getBits bits(sei_size,payload);
                            payload+=sei_size;
                            *recoveryLength=bits.getUEG();
                            aprintf("[SEI] Recovery :%"PRIu32"\n",*recoveryLength);
                            r=true;
                            break;
                        }
                        default:
                            payload+=sei_size;
                            break;
                }
    }
    //if(payload+1<tail) ADM_warning("Bytes left in SEI %d\n",(int)(tail-payload));
    return r;
}
uint8_t AVDMBufferedAudioStream::goToTime(uint32_t newoffset) {
        ADM_assert(!newoffset);
        _instream->goToTime(0);
        _headBuff=_tailBuff=0;
        return 1;
}
void GenericAviSave::guiSetPhasis(const char *str)
{
      ADM_assert(encoding_gui);
      encoding_gui->setPhasis(str);
	
}
uint8_t AVDMBufferedAudioStream::goTo(uint32_t newoffset) {
        ADM_assert(!newoffset);
        goToTime(0);
        return 1;
}
uint8_t		OpenDMLHeader::indexRegular(uint32_t vidTrack)
{
uint32_t fcc,flags,offset,len;
uint32_t count,total=0;
uint32_t trackId,ccType;
uint32_t audioCount[9]={0,0,0,0, 0,0,0,0,0};
uint32_t forward[9];
uint32_t backward[9];
int64_t startOfData;
  
	printf("Trying avi type 1 index\n");
	if(!_regularIndex.offset)
	{
		printf("No regular index\n");
		return 0;
	}
	fseeko(_fd,_regularIndex.offset,SEEK_SET);
	
	// first pass : count how much
	count=_regularIndex.size >> 4;
	while(count)
	{
		fcc=len=0;
		fcc=read32();
		flags=read32();
		offset=read32();
		len=read32();	
		
		if(fcc==MKFCC('r','e','c',' '))
		{
			_recHack=1;
			count--;
			continue;
		}
		
		trackId=((fcc>>8) & 0xFF) -'0';;
		if(trackId>9) trackId=0;
	  	ccType=fcc >>16;
		switch(ccType)
		{
		
		case MKFCC('d','c',0,0):	// video tracks
		case MKFCC('d','b',0,0):
			total++;
			break;
		case MKFCC('w','b',0,0):					
			audioCount[trackId]++;
			break;	
		default:
			printf("Unknown fcc:");fourCC::print(fcc);printf("\n");
		}				
		count--;
		
	}
	
	printf("Found %u videos chunk\n",total);
        for(int i=0;i<9;i++)
                printf("Audio track :%d, %u audio chunk\n",i,audioCount[i]);
	fseeko(_fd,_regularIndex.offset,SEEK_SET);

	_idx=new odmlIndex[total];
	memset(_idx,0,sizeof(odmlIndex)*total);
	count=0;

        int run=0;
        // Pack tracks
        for(int i=0;i<9;i++)
        {
                if(audioCount[i])
                {
                         forward[run]=i;
                         backward[i]=run;
                         run++;
                }
        }
        if(!run) 
        {
            _nbAudioTracks=0;
            printf("No audio chunk found in index..\n");
        }else
            ADM_assert(run==_nbAudioTracks);


        // Create index
        uint32_t nb;
        for(int i=0;i<_nbAudioTracks;i++)
        {
                nb=audioCount[forward[i]];
                _audioTracks[i].index=new odmlIndex[nb+1];
                memset(_audioTracks[i].index,0,(sizeof(odmlIndex)*(nb+1)));
                _audioTracks[i].nbChunks=0;
        }

        uint32_t audiocount=0,videocount=0;
        uint32_t audiototal=0;
        uint32_t audioSize=0;
        odmlIndex *track;
        int     Achunk;
        count=_regularIndex.size >> 4;
        while(count)
	{
_again:
                fcc=len=0;
                fcc=read32();
                flags=read32();
                offset=read32();
                len=read32();
                count--;	
                trackId=((fcc>>8) & 0xFF) -'0';;
                if(trackId>9) trackId=0;
                ccType=fcc >>16;
                if(videocount==0 && audiocount==0) // first chunk met
                {
                        // the first one is at movie_offset-4+8
                        // Its offset + startoff data should be there
                        startOfData=_movi.offset+8;
                        startOfData-=offset;
                        if(_recHack)
                        {
                                startOfData+=4+4+4;
                        }	
                }
                if(fcc==MKFCC('r','e','c',' '))
                {
                        _recHack=1;
                        continue;
                }
                switch(ccType)
                {

                case MKFCC('d','c',0,0):	// video tracks
                case MKFCC('d','b',0,0):
                        _idx[videocount].offset=offset;
                        _idx[videocount].offset+=startOfData;
                        _idx[videocount].size=len;
                        _idx[videocount].intra=flags;
#ifdef ODML_INDEX_VERBOSE			
                        printf("Vid:at %llx size %lu (%lu/%lu) |",_idx[videocount].offset,len,videocount,total);fourCC::print(fcc);printf("|\n");
                        if(offset & 1) printf("!!!! ODD !!!");	
#endif			
                        videocount++;
                        break;
                case MKFCC('w','b',0,0):
                        nb=backward[trackId];
                        ADM_assert(nb<_nbAudioTracks);
                        track=_audioTracks[nb].index;

                        Achunk=_audioTracks[nb].nbChunks;
                        _audioTracks[nb].nbChunks++;

                        track[Achunk].offset=offset;
                        track[Achunk].offset+=startOfData;
                        track[Achunk].size=len;
                        track[Achunk].intra=flags;
                        _audioTracks[nb].totalLen+=len;

                        audioSize+=len;
                        if(offset & 1) printf("!!!! ODD !!!");	
                        audiocount++;	
                        break;	

                default:
                        printf("Idx Regulat: Unknown fcc:");fourCC::print(fcc);printf("\n");
                }	

        }
        _videostream.dwLength= _mainaviheader.dwTotalFrames=total;
        if(total)
                _idx[0].intra=AVI_KEY_FRAME;
        printf("Found %u video \n",total);
        return 1;
}
Beispiel #14
0
/*
   	Uncompress frame, set flags if needed
*/
uint8_t decoderPng::uncompress(ADMCompressedImage * in, ADMImage * out)
{
  int bpp;
  int colortype;

  // Check if it is png, and fill it
  if (!!png_sig_cmp (in->data, 0, 8))

    {
      printf ("[PNG] wrong sig\n");
      return 0;
    }

  //
  //
gain2:
  Init ();
  io.data = in->data;
  io.size = in->dataLength;
  io.cur = 0;
  png_read_png (PNG_PTR, INFO_PTR, PNG_TRANSFORM_IDENTITY, NULL);

  // Check if it is 24 or 32 bits RGB 
  bpp = png_get_bit_depth (PNG_PTR, INFO_PTR);
//   printf("Bpp:%u\n",bpp);
  // if needed we change colorspace 
  colortype = png_get_color_type (PNG_PTR, INFO_PTR);
  // 
  if (colorspace == ADM_COLOR_RGB24 && colortype == PNG_COLOR_TYPE_RGB_ALPHA)	// RGB32
    {

      // Switch to 32 bits
      colorspace = ADM_COLOR_RGB32A;
      recalc ();
      goto gain2;
    }

  else if (colorspace == ADM_COLOR_RGB32A && colortype == PNG_COLOR_TYPE_RGB)

    {

      // Switch to 24 bits
      colorspace = ADM_COLOR_RGB24;
      recalc ();
      goto gain2;
    }
  ADM_assert (out->_isRef);
  out->_planes[0] = decoded;
  out->_planes[1] = NULL;
  out->_planes[2] = NULL;
  if (colorspace == ADM_COLOR_RGB32A)
    out->_planeStride[0] = _w * 4;

  else
    out->_planeStride[0] = _w * 3;
  out->_planeStride[1] = 0;
  out->_planeStride[2] = 0;
  out->_colorspace = colorspace;
  Cleanup ();
  return 1;
}
/**
 * \fn GUI_FileSelWrite
 * \brief Select a file for Writing, when ok the CB callback is called with the name as argument
 */	
void GUI_FileSelWrite(const char *label,SELFILE_CB *cb) 
{
	ADM_assert(fileSelDescriptor);
	return fileSelDescriptor->fileWriteCb(label,cb);	
}
Beispiel #16
0
/**
 * \fn automation
 * @return 
 */
int automation(void )

{
static char **argv;
static int argc;
static int cur;
static int myargc;
static int index;
static three_arg_type three;
static two_arg_type two;

    argc=global_argc;
    argv = global_argv;

      //the port change has to be done before the video load
      for( int runParaSearch=2 ; runParaSearch < argc ; ){
          if(*argv[runParaSearch] == '-' && *(argv[runParaSearch]+1) == '-')
          {
              index = searchReactionTable(argv[runParaSearch]+2);
              if(index != -1)
              {
                  if(!strcmp(avs_port_change, argv[runParaSearch] +2 ))
                  {
                      A_set_avisynth_port(argv[runParaSearch+1]);
                      break;
                  }
                  runParaSearch += reaction_table[index].have_arg +1;
              }
              else
                  runParaSearch += 1;
          }
          else
              runParaSearch += 1;
      }

    printf("\n *** Automated : %" PRIu32" entries*************\n",(uint32_t)NB_AUTO);
    // we need to process
    argc-=1;
    cur=1;
    myargc=argc;
    while(myargc>0)
    {
                if(( *argv[cur]!='-') || (*(argv[cur]+1)!='-'))
                {
                      if(cur==1)
                      {
                          loadCB(argv[cur]);
                      }
                      else
                          printf("\n Found garbage %s\n",argv[cur]);
                      cur+=1;myargc-=1;
                      continue;
                }
                // else it begins with --
                if(!strcmp(argv[cur]+2,"portable")) // portable mode switch has been already taken care of, ignore
                {
                    cur++;
                    myargc--;
                    continue;
                }
                index= searchReactionTable(argv[cur]+2);
                if(index==-1) // not found
                {
                                                printf("\n Unknown command :%s\n",argv[cur] );
                                                cur+=1;myargc-=1;
                }
                else
                {
                    printf("%s-->%d\n", reaction_table[index].string,reaction_table[index].have_arg);
                    one_arg_type call=reaction_table[index].callback;
                    switch(  reaction_table[index].have_arg)
                    {
                        case 3:
                                  three=(three_arg_type)call;
                                  three( argv[cur+1],argv[cur+2],argv[cur+3]);
                                  break;
                        case 2:
                                  two=(two_arg_type)call;
                                  two( argv[cur+1],argv[cur+2]);
                                  break;
                        case 1:
                                  call(argv[cur+1]);
                                  break;
                        case 0:
                                  call(NULL);
                                  break;
                        default:
                                  ADM_assert(0);
                                  break;
                    }
                    cur+=1+reaction_table[index].have_arg;
                    myargc-=1+reaction_table[index].have_arg;
                }
    } // end while
    GUI_Verbose();
    printf("\n ********** Automation ended***********\n");
    return 0; // Do not call me anymore
}
/**
 * \fn GUI_FileSelRead
 * \brief Select a file for reading, name is allocated with a copy of the name, null if fail.
 */	
void GUI_FileSelRead(const char *label,char * * name) 
{
	ADM_assert(fileSelDescriptor);
	return fileSelDescriptor->fileReadName(label,name);	
}
Beispiel #18
0
int preferences::set_lastfile(const char* file){
   char *internal_file;
	if( ! file ){
		fprintf(stderr,"Prefs: set_lastfile(NULL) called\n");
		return RC_FAILED;
	}
	internal_file = ADM_PathCanonize(file);
	if( !internal_file ){
		fprintf(stderr,"Prefs: set_lastfile(): PathCanonize() returns NULL\n");
		return RC_FAILED;
        }
#ifdef DEBUG_PREFS
	fprintf(stderr,"Prefs: set_lastfile(%s)\n",file);
	if( strcmp(file,internal_file) )
		fprintf(stderr,"Prefs: set_lastfile(%s) (with appended current dir)\n",internal_file);
	PRT_LAFI("<= LASTFILES_",1,opt_defs[LASTFILES_FILE1].current_val);
	PRT_LAFI("<= LASTFILES_",2,opt_defs[LASTFILES_FILE2].current_val);
	PRT_LAFI("<= LASTFILES_",3,opt_defs[LASTFILES_FILE3].current_val);
	PRT_LAFI("<= LASTFILES_",4,opt_defs[LASTFILES_FILE4].current_val);
#endif
	// change opt_defs array
	//
	// ToDo:
	// * a call with a file already in lastfiles will resort lastfiles with
	//   the actual argument on top
	// * a call with a file new to lastfiles will drop LASTFILE_4, move all
	//   one step down and add the file as LASTFILE_1
	if( opt_defs[LASTFILES_FILE4].current_val &&
	    !strncmp(opt_defs[LASTFILES_FILE4].current_val,internal_file,strlen(opt_defs[LASTFILES_FILE4].current_val)) ){
	  char *x = opt_defs[LASTFILES_FILE4].current_val;
		opt_defs[LASTFILES_FILE4].current_val = opt_defs[LASTFILES_FILE3].current_val;
		opt_defs[LASTFILES_FILE3].current_val = opt_defs[LASTFILES_FILE2].current_val;
		opt_defs[LASTFILES_FILE2].current_val = opt_defs[LASTFILES_FILE1].current_val;
		opt_defs[LASTFILES_FILE1].current_val = x;
	}else if( opt_defs[LASTFILES_FILE3].current_val &&
            !strncmp(opt_defs[LASTFILES_FILE3].current_val,internal_file,strlen(opt_defs[LASTFILES_FILE3].current_val)) ){
          char *x = opt_defs[LASTFILES_FILE3].current_val;
		opt_defs[LASTFILES_FILE3].current_val = opt_defs[LASTFILES_FILE2].current_val;
                opt_defs[LASTFILES_FILE2].current_val = opt_defs[LASTFILES_FILE1].current_val;
                opt_defs[LASTFILES_FILE1].current_val = x;
        }else if( opt_defs[LASTFILES_FILE2].current_val &&
            !strncmp(opt_defs[LASTFILES_FILE2].current_val,internal_file,strlen(opt_defs[LASTFILES_FILE2].current_val)) ){
          char *x = opt_defs[LASTFILES_FILE2].current_val;
		opt_defs[LASTFILES_FILE2].current_val = opt_defs[LASTFILES_FILE1].current_val;
		opt_defs[LASTFILES_FILE1].current_val = x;
	}else if( opt_defs[LASTFILES_FILE1].current_val &&
            !strncmp(opt_defs[LASTFILES_FILE1].current_val,internal_file,strlen(opt_defs[LASTFILES_FILE1].current_val)) ){
		; // nothing to do - always on top
	}else{
		if( opt_defs[LASTFILES_FILE4].current_val )
			ADM_dealloc(opt_defs[LASTFILES_FILE4].current_val);
		opt_defs[LASTFILES_FILE4].current_val = opt_defs[LASTFILES_FILE3].current_val;
		opt_defs[LASTFILES_FILE3].current_val = opt_defs[LASTFILES_FILE2].current_val;
		opt_defs[LASTFILES_FILE2].current_val = opt_defs[LASTFILES_FILE1].current_val;
		opt_defs[LASTFILES_FILE1].current_val = ADM_strdup(internal_file);
	}

#ifdef USE_LIBXML2
	// change the xmlDocument
	if( ! xdoc ){
		// no .avidemuxrc file or not loaded yet
		load();          // try to load it
		if( ! xdoc ){    // really: no .avidemuxrc file
			save();  // generate one from internal defaults and actual changes
			if( xdoc )
				erase_blank_nodes(xdoc->children);
		}
	}
	if( ! xdoc ){
		fprintf(stderr,"Prefs: no xml document generated ny load() nor save()\n");
	}else{
	  xmlNodePtr p;
	  xmlNodePtr q;
		// we assume a valid xml document, but maybe an older version
		ADM_assert( xdoc->children );
		p = xdoc->children;				// ->avidemux (should be there)
		p = goto_node_with_create(p, "lastfiles");	// ->avidemux->lastfile
		q = goto_node_with_create(p, "file1");		// ->avidemux->lastfile->1
		xmlNodeSetContent( q,
			(xmlChar*)(opt_defs[LASTFILES_FILE1].current_val?opt_defs[LASTFILES_FILE1].current_val:""));
		q = goto_node_with_create(p, "file2");		// ->avidemux->lastfile->2
		xmlNodeSetContent( q,
			(xmlChar*)(opt_defs[LASTFILES_FILE2].current_val?opt_defs[LASTFILES_FILE2].current_val:""));
		q = goto_node_with_create(p, "file3");		// ->avidemux->lastfile->3
		xmlNodeSetContent( q,
			(xmlChar*)(opt_defs[LASTFILES_FILE3].current_val?opt_defs[LASTFILES_FILE3].current_val:""));
		q = goto_node_with_create(p, "file4");		// ->avidemux->lastfile->4
		xmlNodeSetContent( q,
			(xmlChar*)(opt_defs[LASTFILES_FILE4].current_val?opt_defs[LASTFILES_FILE4].current_val:""));
		save_xml_to_file();
	}
#endif

#ifdef DEBUG_PREFS
	PRT_LAFI("=> LASTFILES_",1,opt_defs[LASTFILES_FILE1].current_val);
	PRT_LAFI("=> LASTFILES_",2,opt_defs[LASTFILES_FILE2].current_val);
	PRT_LAFI("=> LASTFILES_",3,opt_defs[LASTFILES_FILE3].current_val);
	PRT_LAFI("=> LASTFILES_",4,opt_defs[LASTFILES_FILE4].current_val);
#endif
	delete[] internal_file;
	return RC_OK;
}
/**
 * \fn FileSel_SelectRead
 * \brief Select a file for Reading, name is allocated with a copy of the name, null if fail.
 * @param title : [in] Title of the dialog box
 * @param target: [in/out] Buffer that will hold the name, must be at least max bytes big
 * @param max : [in] Max number of bytes the buffer will hold
 * @param source : [in] Initial value for the file, can be null
 */	
uint8_t FileSel_SelectRead(const char *title,char *target,uint32_t max, const char *source)
{
	ADM_assert(fileSelDescriptor);
	return fileSelDescriptor->fileSelectRead(title,target,max, source);
}
uint8_t ADM_queue::isEmpty(void)
{
  if(head) return 0;
  ADM_assert(!tail);
  return 1; 
}
Decimate::Decimate(AVDMGenericVideoStream *in,CONFcouple *couples)		
{
{
		
		int count = 0;
		char buf[80];
		unsigned int *p;

		_in=in;		
   		memcpy(&_info,_in->getInfo(),sizeof(_info));    
  		_info.encoding=1;
		_uncompressed=NULL;		
  		_info.encoding=1;
		
		//		
		// Init here
		debug=0;
		show=0;		
#ifdef USE_SSE	
		if(CpuCaps::hasSSE())
		{
			printf("Decimate:SSE enabled\n");
		}
#endif
		//
		_param=new DECIMATE_PARAM;
		if(couples)
		{
			GET(cycle);
			GET(mode);
			GET(quality);
			GET(threshold);
			GET(threshold2);
			
		}
		else // Default
  		{
			_param->cycle=5;
			_param->mode=0;
			_param->quality=2;
			_param->threshold=0;
			_param->threshold2=3.0;
		}
		
		ADM_assert(_param->cycle);
		vidCache=new VideoCache(_param->cycle*2+1,in);
		
		if (_param->mode == 0 || _param->mode == 2 || _param->mode == 3)
		{
			num_frames_hi = _info.nb_frames;
			_info.nb_frames = _info.nb_frames * (_param->cycle - 1) / _param->cycle;
			_info.fps1000=_info.fps1000*(_param->cycle-1);
			_info.fps1000=(uint32_t)(_info.fps1000/_param->cycle);
			
		}
		last_request = -1;
		firsttime = true;
		sum = (unsigned int *) ADM_alloc(MAX_BLOCKS * MAX_BLOCKS * sizeof(unsigned int));
		ADM_assert(sum);		
		all_video_cycle = true;

		if (debug)
		{
			char b[80];
			sprintf(b, "Decimate %s by Donald Graft, Copyright 2003\n", VERSION);
			OutputDebugString(b);
		}
	}
}
uint8_t oplug_mpegff(const char *name, ADM_OUT_FORMAT type)
{
AVDMGenericVideoStream *_incoming;
//EncoderFFMPEGMpeg1  *encoder;
Encoder  *encoder;

ADMMpegMuxer	*muxer=NULL;
FILE 		*file=NULL;
uint8_t		audioBuffer[48000];
uint32_t	audioLen=0;
uint32_t _w,_h,_fps1000,_page,total;	
AVDMGenericAudioStream	*audio;
uint32_t len,flags;
uint32_t size;
ADM_MUXER_TYPE mux;
uint32_t  audio_encoding=0;
uint32_t  real_framenum=0;
uint8_t   ret=0;
uint32_t  sample_target=0;
uint32_t  total_sample=0;
ADMBitstream bitstream(0);
uint32_t audioSum=0;

        twoPass=new char[strlen(name)+6];
        twoFake=new char[strlen(name)+6];
  
        strcpy(twoPass,name);
        strcat(twoPass,".stat");
        /* orig: strcat(twoFake,".fake"); */

        strcpy(twoFake,name);
        strcat(twoFake,".fake");
 
        _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart);
        _w=_incoming->getInfo()->width;
        _h=_incoming->getInfo()->height;
        _fps1000=_incoming->getInfo()->fps1000;
        _page=_w*_h;
        _page+=_page>>1;

        total=_incoming->getInfo()->nb_frames;
        if(!total) return 0;	
        
        switch(type)
        {
            default:
                    ADM_assert(0);
            case ADM_ES:
                        // Else open file (if possible)                       
                        mux=MUXER_NONE;
                        break;
            case ADM_TS:
                    if(!currentaudiostream)
                    {
                      GUI_Error_HIG(_("There is no audio track"), NULL);
                        return 0;
                    }
                    audio=mpt_getAudioStream();
                    mux=MUXER_TS;
                    break;
            case ADM_PS:
            
            {
                if(!currentaudiostream)
                {
                  GUI_Error_HIG(_("There is no audio track"), NULL);
                        return 0;
                }
                audio=mpt_getAudioStream();
                // Have to check the type
                // If it is mpeg2 we use DVD-PS
                // If it is mpeg1 we use VCD-PS
                // Later check if it is SVCD
                if(!audio)
                {
                  GUI_Error_HIG(_("Audio track is not suitable"), NULL);
                        return 0;
                }
                // Check
                WAVHeader *hdr=audio->getInfo();	
                audio_encoding=hdr->encoding;
                if(current_codec==CodecXVCD ||current_codec==CodecVCD)
                {
                        if(hdr->frequency!=44100 ||  hdr->encoding != WAV_MP2)
                        {
                            GUI_Error_HIG(("Incompatible audio"),_( "For VCD, audio must be 44.1 kHz MP2."));
                            deleteAudioFilter(audio);
                            return 0;
                        }
                        mux=MUXER_VCD;
                        printf("X*CD: Using VCD PS\n");
                }else
                {    
                        aviInfo info;
                        video_body->getVideoInfo(&info);
                        if(hdr->frequency==44100 && _w==480&&hdr->encoding == WAV_MP2 ) // SVCD ?
                        {
                            mux=MUXER_SVCD;
                            printf("X*VCD: Using SVCD PS\n");
                        }
                        else
                        {
                            // mpeg2, we do only DVD right now
                            if(hdr->frequency!=48000 || 
                                (hdr->encoding != WAV_MP2 && hdr->encoding!=WAV_AC3 && hdr->encoding!=WAV_LPCM))
                            {
                                deleteAudioFilter(audio);
                                GUI_Error_HIG(_("Incompatible audio"), _("For DVD, audio must be 48 kHz MP2, AC3 or LPCM."));
                                return 0 ;
                            }
                            mux=MUXER_DVD;
                            printf("X*VCD: Using DVD PS\n");
                        }
                }
            }
         }        
        // Create muxer
       
       
        switch(current_codec)
        {
                
                case CodecXVCD:
                        encoder=new EncoderFFMPEGMpeg1(FF_MPEG1,&ffmpeg1Codec);
                        printf("\n Using ffmpeg mpeg1 encoder\n");
                        break;
                case CodecXSVCD:
                        encoder=new EncoderFFMPEGMpeg1(FF_MPEG2,&ffmpeg2SVCDCodec);
                        printf("\n Using ffmpeg mpeg2 encoder\n");
                        break;
                case CodecXDVD:
                        encoder=new EncoderFFMPEGMpeg1(FF_MPEG2,&ffmpeg2DVDCodec);
                        printf("\n Using ffmpeg mpeg2 encoder (DVD)\n");
                        break;
                case CodecDVD:
                  encoder=new EncoderMpeg2enc(MPEG2ENC_DVD,&DVDCodec);
                  printf("\n Using mpeg2enc encoder (DVD)\n");
                  break;
                case CodecRequant:
                  if(!isMpeg12Compatible(avifileinfo->fcc))
                  {
                    GUI_Error_HIG("Incompatible Input","The input file must be mpeg2 to be able to use requant!");
                    return 0; // Fixme, do some cleanup 
                  }
                  encoder=new EncoderRequant(&RequantCodec);
                  printf("\n Using mpeg2 requant\n");
                  break;
                break;
                case CodecSVCD:
                  encoder=new EncoderMpeg2enc(MPEG2ENC_SVCD,&SVCDCodec);
                  printf("\n Using mpeg2enc encoder (SVCD)\n");
                  break;
                case CodecVCD:
                  encoder=new EncoderMpeg2enc(MPEG2ENC_VCD,&VCDCodec);
                  printf("\n Using mpeg2enc encoder (VCD)\n");
                  break;
                default:
                ADM_assert(0);
      }

      encoder->setLogFile(twoPass,total);
      if(!encoder->configure(_incoming))
      {
              delete encoder;
              return 0;
      }


      _buffer=new uint8_t[_page]; // Might overflow if _page only
      _outbuffer=new uint8_t[_page];

      ADM_assert(  _buffer);
      ADM_assert(  _outbuffer);
    
      DIA_encoding  *encoding;
      encoding =new DIA_encoding(_fps1000);
      switch(current_codec)
      {
          case CodecVCD:
            encoding->setCodec("libmpeg2enc VCD");
            break;
          case CodecSVCD:
            encoding->setCodec("libmpeg2enc SVCD");
            break;
          case CodecDVD:
            encoding->setCodec("libmpeg2enc DVD");
            break;
          case CodecXVCD:
            encoding->setCodec("FFmpeg Mpeg1 VBR");
            break;
          case CodecXSVCD:
            encoding->setCodec("FFmpeg Mpeg2 SVCD VBR");
            break;
          case CodecXDVD:
            encoding->setCodec("FFmpeg Mpeg2 DVD VBR");
            break;
          case CodecRequant:
            encoding->setCodec("Mpeg Requantizer");
            break;
          
          default:
            ADM_assert(0);
	}
        switch(mux)
          {
            case MUXER_NONE:encoding->setContainer("Mpeg ES");break;
            case MUXER_TS:  encoding->setContainer("Mpeg TS");break;
            case MUXER_VCD: encoding->setContainer("Mpeg VCD");break;
            case MUXER_SVCD:encoding->setContainer("Mpeg SVCD");break;
            case MUXER_DVD: encoding->setContainer("Mpeg DVD");break;
            default:
                ADM_assert(0);
          }



        // pass 1
        if(encoder->isDualPass())
        {
                        FILE *fd;
                        uint8_t reuse=0;
                        fd=fopen(twoPass,"rt");
                        if(fd)
                        {
                          if(GUI_Question(_("Reuse log file ?")))
                                {
                                        reuse=1;
                                }
                                fclose(fd);
                        }
                        if(!reuse)
                        {
                                encoding->setPhasis ("Pass 1/2");
                                encoder->startPass1();
                                bitstream.data=_buffer;
                                bitstream.bufferSize=_page;
                                for(uint32_t i=0;i<total;i++)
                                {
                                        bitstream.cleanup(i);
                                        if(!encoder->encode( i, &bitstream))//&len,(uint8_t *) _buffer,&flags))
                                        {
                                          GUI_Error_HIG(_("Error in pass 1"), NULL);
                                        }
                                        encoding->setFrame(i,bitstream.len,bitstream.out_quantizer,total);
                                        if(!encoding->isAlive())
                                        {

                                              goto finishvcdff;
                                        }
                                }
                        }
                        encoder->startPass2();
                        encoding->reset();
                }
                
              switch(type)
              {
                case ADM_PS:
                  muxer=new mplexMuxer;
                  break;
                case ADM_TS:
                  muxer=new tsMuxer;
                  break;
                case ADM_ES:
                  break;
                default:
                  ADM_assert(0);
      
      
              }
              if(muxer)
              {
                if(!muxer->open(name,0,mux,avifileinfo,audio->getInfo()))
                {
                  delete muxer;
                  muxer=NULL;
                  deleteAudioFilter(audio);
                  printf("Muxer init failed\n");
                  return 0 ;
                }
                double sample_time;

                sample_time=total;
                sample_time*=1000;
                sample_time/=_fps1000; // target_time in second
                sample_time*=audio->getInfo()->frequency;
                sample_target=(uint32_t)floor(sample_time);
              }
              else
              {
                file=fopen(name,"wb");
                if(!file)
                {
                  GUI_Error_HIG(_("File error"), _("Cannot open \"%s\" for writing."), name);
                  return 0 ;
                }
              }
          if(encoder->isDualPass())
                  encoding->setPhasis ("Pass 2/2");
          else
                  encoding->setPhasis ("Encoding");

         // Set info for audio if any
         if(muxer)
         {
            if(!audioProcessMode())
                  encoding->setAudioCodec("Copy");
            else
                  encoding->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding));
         }
         //**********************************************************
         //  In that case we do multithreadedwriting (yes!)
         //**********************************************************

         if(mux==MUXER_DVD || mux==MUXER_SVCD || mux==MUXER_VCD)
         {
           pthread_t audioThread,videoThread,muxerThread;
           muxerMT context;
           //
           bitstream.data=_outbuffer;
           bitstream.bufferSize=_page;
           // 
           memset(&context,0,sizeof(context));
           context.videoEncoder=encoder;
           context.audioEncoder=audio;
           context.muxer=(mplexMuxer *)muxer;
           context.nbVideoFrame=total;
           context.audioTargetSample=sample_target;
           context.audioBuffer=audioBuffer;
           context.bitstream=&bitstream;
           context.opaque=(void *)encoding;

           // start audio thread
           ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioSlave,&context)); 
           ADM_assert(!pthread_create(&videoThread,NULL,(THRINP)defaultVideoSlave,&context)); 
           while(1)
           {
             accessMutex.lock();
             if(!encoding->isAlive())
             {
               context.audioAbort=1;
               context.videoAbort=1;
               printf("[mpegFF]Waiting for slaves\n");
               accessMutex.unlock();
               while(1)
               {
                 accessMutex.lock();
                 if(context.audioDone && context.videoDone)
                 {
                   printf("[mpegFF]Both audio & video done\n");
                   if(context.audioDone==1 && context.videoDone==1) ret=1;
                   else ret=0;
                   accessMutex.unlock();
                   goto finishvcdff;
                 }
                 accessMutex.unlock();
                 ADM_usleep(50000);
 
               }
               
             }
             if(context.audioDone==2 || context.videoDone==2 ) //ERROR
             {
               context.audioAbort=1;
               context.videoAbort=1;
             }
             if(context.audioDone && context.videoDone)
             {
               printf("[mpegFF]Both audio & video done\n");
               if(context.audioDone==1 && context.videoDone==1) ret=1;
               else ret=0;
               accessMutex.unlock();
               goto finishvcdff;
             }
             accessMutex.unlock();
             ADM_usleep(1000*1000);
             
           }
           
         }
         //**********************************************************
         //  NOT MULTITHREADED
         //**********************************************************

      bitstream.data=_outbuffer;
      for(uint32_t i=0;i<total;i++)
      {
       	// get frame
                bitstream.cleanup(i);
                if(!encoder->encode( i,&bitstream))// &len,(uint8_t *) _outbuffer,&flags))
                {
                  GUI_Error_HIG(_("Error in pass 2"), NULL);
                        goto finishvcdff;
                }
                if(!bitstream.len) continue;
                
                if(file)
                {
                    fwrite(_outbuffer,bitstream.len,1,file);
                }
                else
                {
                        uint32_t samples; 
                        
                        //printf("%lu %lu\n",i,dts);
                        
                        muxer->writeVideoPacket(&bitstream);
                        real_framenum++;
                        // _muxer->writeVideoPacket(len,_buffer_out,
                        //i-MPEG_PREFILL,_codec->getCodedPictureNumber());
                        if(total_sample<sample_target)
                        {
                            while(muxer->needAudio() && total_sample<sample_target) 
                            {				
                                if(!audio->getPacket(audioBuffer, &audioLen, &samples))	
                                { 
                                        break; 
                                }
                                if(audioLen) 
                                {
                                        muxer->writeAudioPacket(audioLen,audioBuffer); 
                                        total_sample+=samples;
                                        audioSum+=audioLen;
                                }
                            }
                        }
                
                }
                encoding->setFrame(i,bitstream.len,bitstream.out_quantizer,total);
                encoding->setAudioSize(audioSum);
                if(!encoding->isAlive ())
                        {
                                  ret=0;        
                                  goto finishvcdff;
                        }
        }
        ret=1;
finishvcdff:
        printf("[MPEGFF] Finishing..\n");
        delete encoding;
        end();
        if(file)
        {
                fclose(file);
                file=NULL;
        }
        else
        {  
            if(muxer)
            {
                muxer->close();
                delete muxer;
                muxer=NULL;
            }
        }
        delete encoder;
        return ret;
}
//______________________________
uint8_t EncoderFFMPEG::encode (uint32_t frame, ADMBitstream *out)
{
  uint32_t l, f;
  //ENC_RESULT enc;

  ADM_assert (_codec);
  ADM_assert (_in);

  if (frame != UINT32_MAX)
  {
	  if (!_in->getFrameNumberNoAlloc (frame, &l, _vbuffer, &f))
	  {
		  printf ("\n Error : Cannot read incoming frame !");
		  return 0;
	  }
  }

  switch (_state)
    {
    case enc_CBR:
    case enc_CQ:
      return _codec->encode (frame == UINT32_MAX ? NULL : _vbuffer, out );
      break;
    case enc_Same:
      {
		  if (frame != UINT32_MAX)
		  {
			  if (_vbuffer->flags & AVI_KEY_FRAME)
				  out->flags = AVI_KEY_FRAME;
			  else
				  out->flags = 0;

			  int inq = _vbuffer->_Qp;

			  if (inq > 31)
				  inq = 31;

			  if (inq < 2)
				  inq = 2;

			  out->in_quantizer = inq;
		  }

	if (!_codec->encode (frame == UINT32_MAX ? NULL : _vbuffer, out ))
	  {
	    printf ("\n codec error on 1st pass !");
	    return 0;
	  }
	//printf("Inq:%lu outq:%lu\n",inq,enc.out_quantizer);                       
	_frametogo++;
	return 1;
	break;
      }
    case enc_Pass1:

      //              ADM_assert(fd);
      if (!_codec->encode (frame == UINT32_MAX ? NULL : _vbuffer, out ))
	{
	  printf ("\n codec error on 1st pass !");
	  return 0;
	}
      _frametogo++;
      return 1;
      break;
    case enc_Pass2:
      // Encode it !
      if (!_codec->encode (frame == UINT32_MAX ? NULL : _vbuffer, out ))
            return 0;
      return 1;
      break;

    default:
      ADM_assert (0);
    }
  return 0;
}
/**
      \fn getFFCompressParams
      \brief Dialog for lavcodec mpeg4/... codec settings
*/
uint8_t DIA_xvid4(COMPRES_PARAMS *incoming)
{
int b;
int ret=0;
int code;
      xvid4EncParam localParam;
      ADM_assert(incoming->extraSettingsLen==sizeof(localParam));
      memcpy(&localParam,incoming->extraSettings,sizeof(localParam));
#define PX(x) &(localParam.x)
         // Our tabs
         /* Tab 1 main */
           diaElemBitrate bitrate(incoming,NULL);
#define MKTOGGLE(y,x)           diaElemToggle  t_##x(PX(x),y)
        MKTOGGLE(QT_TR_NOOP("_Interlaced"),	    interlaced);
        MKTOGGLE(QT_TR_NOOP("Ca_rtoon mode"),      cartoon);
        MKTOGGLE(QT_TR_NOOP("_Greyscale"),         greyscale);
        MKTOGGLE(QT_TR_NOOP("Turbo mode"),      turbo);
        MKTOGGLE(QT_TR_NOOP("C_hroma optimizer"),         chroma_opt);
        diaElem *main[]={&bitrate,&t_interlaced,&t_cartoon,&t_greyscale,&t_turbo,&t_chroma_opt};
        diaElemTabs tabMain(QT_TR_NOOP("Main"),6,main);
         /* Tab 2 motion */
         diaMenuEntry motionMenu[] = {
                             {0,       QT_TR_NOOP("None"),NULL}
                            ,{1,      QT_TR_NOOP("Very Low"),NULL}
                            ,{2,      QT_TR_NOOP("Low"),NULL}
                            ,{3,      QT_TR_NOOP("Medium"),NULL}
                            ,{4,      QT_TR_NOOP("High"),NULL}
                            ,{5,      QT_TR_NOOP("Very High"),NULL}
                            ,{6,      QT_TR_NOOP("Ultra High"),NULL}};
        diaElemMenu motion(PX(guiLevel),QT_TR_NOOP("Motion Search Precision"),7,motionMenu);
        
         diaMenuEntry vhqMenu[] = {
                             {0,       QT_TR_NOOP("Off"),NULL}
                            ,{1,      QT_TR_NOOP("Mode Decision"),NULL}
                            ,{2,      QT_TR_NOOP("Limited Search"),NULL}
                            ,{3,      QT_TR_NOOP("Medium Search"),NULL}
                            ,{4,      QT_TR_NOOP("Wide Search"),NULL} };
         diaElemMenu vhq(PX(vhqmode),QT_TR_NOOP("VHQ Mode"),5,vhqMenu);
        
        
        /* Tab2-ASP */
          diaElemUInteger  bframe(PX(bframes),QT_TR_NOOP("Max B Frames"),0,3);
          diaElemToggle    qpel(PX(qpel),QT_TR_NOOP("Quarter Pixel"));
          diaElemToggle    gmc(PX(gmc),QT_TR_NOOP("GMC"));
          diaElemToggle    bvhq(PX(bvhq),QT_TR_NOOP("BVHQ"));
          diaElemFrame  frameASP(QT_TR_NOOP("Advanced Simple Profile"));
          frameASP.swallow(&bframe);
          frameASP.swallow(&qpel);
          frameASP.swallow(&gmc);
          frameASP.swallow(&bvhq);
        
         
          /* Tab 2 motion extra */
            diaElemToggle    inter4mv(PX(inter4mv),QT_TR_NOOP("4MV"));
            diaElemToggle    chroma_me(PX(chroma_me),QT_TR_NOOP("Chroma ME"));
            diaElemToggle    hqac(PX(chroma_me),QT_TR_NOOP("HQ AC"));
          diaElemFrame  frameMore(QT_TR_NOOP("More Search"));
          frameMore.swallow(&inter4mv);
          frameMore.swallow(&chroma_me);
          frameMore.swallow(&hqac);
          /* Tab 2 gop size */
          diaElemUInteger  min_key_interval(PX(min_key_interval),QT_TR_NOOP("Min Gop Size"),1,900);
          diaElemUInteger  max_key_interval(PX(max_key_interval),QT_TR_NOOP("Max Gop Size"),1,900);
            diaElemFrame  frameGop(QT_TR_NOOP("GOP Size"));
              frameGop.swallow(&min_key_interval);
              frameGop.swallow(&max_key_interval);
            
           diaElem *motions[]={&motion,&vhq,&frameMore,&frameGop,&frameASP};
          diaElemTabs tabMotion(QT_TR_NOOP("Motion"),5,motions);
        /* Tab 3 Qz*/
          diaMenuEntry qzMenu[] = {
                             {0,       QT_TR_NOOP("H263"),NULL}
                            ,{1,      QT_TR_NOOP("Mpeg"),NULL}}                            ;
           diaElemMenu h263(PX(mpegQuantizer),QT_TR_NOOP("Quantization Matrix"),2,qzMenu);
           diaElemToggle    trellis(PX(trellis),QT_TR_NOOP("Trellis Quantization"));
           
           
          diaElem *qz[]={&h263,&trellis};
          diaElemTabs tabQz(QT_TR_NOOP("Quantization"),2,qz);
          
          /* Tab 4 : 2nd pass */
#define MKENTRY(y,x) diaElemUInteger x(PX(x),y,0,100); frameOne.swallow(&x);
        diaElemFrame  frameOne(QT_TR_NOOP("Two Pass Tuning")); 
         
        MKENTRY(QT_TR_NOOP("Key Frame Boost(%)"), keyframe_boost);
        
        MKENTRY(QT_TR_NOOP("I-frames closer than..."), kfthreshold);
        MKENTRY(QT_TR_NOOP(".. are reduced by(%)"), kfreduction);
        MKENTRY(QT_TR_NOOP("Max Overflow Improvement(%)"), max_overflow_improvement);
        MKENTRY(QT_TR_NOOP("Max Overglow Degradation(%)"), max_overflow_degradation);

#undef MKENTRY
#define MKENTRY(y,x) diaElemUInteger  x(PX(x),y,0,100);frameTwo.swallow(&x);
        diaElemFrame  frameTwo(QT_TR_NOOP("Curve Compression"));  

        MKENTRY(QT_TR_NOOP("High Bitrate Scenes (%)"), curve_compression_high);
        MKENTRY(QT_TR_NOOP("Low Bitrate Scenes (%)"), curve_compression_low);
        MKENTRY(QT_TR_NOOP("Overflow Control Strength"), overflow_control_strength);

         diaElem *twopass[]={&frameOne,&frameTwo};
          diaElemTabs tabPass(QT_TR_NOOP("Two Pass"),2,twopass);
        /**/
        
        
          
          /* End of tabs */
        diaElemTabs *tabs[4]={&tabMain,&tabMotion,&tabQz,&tabPass};
        if( diaFactoryRunTabs(QT_TR_NOOP("Xvid4 Configuration"),4,tabs))
	{
           memcpy(incoming->extraSettings,&localParam,sizeof(localParam));
           return 1;
        }
         return 0;
}
// Dummy ones
uint8_t	ADM_ogmWrite::initVideo(const char *name)
{
		ADM_assert(0);
		return 0;

}
uint8_t ADMVideoStabilize::getFrameNumberNoAlloc(uint32_t frame,
				uint32_t *len,
   				ADMImage *data,
				uint32_t *flags)
{
UNUSED_ARG(flags);
uint32_t uvlen;
uint32_t dlen,dflags;

ADMImage	*_next;
ADMImage	*_previous;  	
ADMImage	*_current;
		
		uvlen=    _info.width*_info.height;
		*len=uvlen+(uvlen>>1);
		if(frame> _info.nb_frames-1) return 0;
		_current=vidCache->getImage(frame);
		if(!_current) return 0;
		data->copyInfo(_current);
		if(!frame || (frame==_info.nb_frames-1))
		{

			data->duplicate(_current);
			vidCache->unlockAll();
			return 1;
		}	 
   		_previous=vidCache->getImage(frame-1);		
		if(!_previous)
		{
			vidCache->unlockAll();
			return 0;
		}
   		_next=vidCache->getImage(frame+1);
		if(!_next)
		{
			vidCache->unlockAll();
			return 0;
		}
		
           // for u & v , no action -> copy it as is
           memcpy(UPLANE(data),UPLANE(_current),uvlen>>2);
	   memcpy(VPLANE(data),VPLANE(_current),uvlen>>2);

           uint8_t *inprev,*innext,*incur,*zout;
              
              inprev=YPLANE(_previous)+1+_info.width;
              innext=YPLANE(_next)+1+_info.width;
              incur =YPLANE(_current)+1+_info.width;
              
              zout=YPLANE(data)+_info.width+1;
              
             
              uint8_t *nl,*pl,*nc,*pc;
              
              uint16_t c,coeff;
              uint32_t x;
              for(uint32_t y= _info.height-1;y>1;y--)
              	{
			nl=incur+_info.width;
			pl=incur-_info.width;
			nc=incur+1;
			pc=incur-1;		   
								   
		        for(x= _info.width-1;x>1;x--)
        		{
	               		c=*incur*4;;
	                    	coeff=4;
#define PONDERATE(x,p) if(distMatrix[*incur][x]<*_param)	                      \
{ c+=x;coeff++;}
																PONDERATE(*innext,1);
				PONDERATE(*inprev,1);
				PONDERATE(*(pc),1);
				PONDERATE(*(nc),1);
				PONDERATE(*(nl),1);
				PONDERATE(*(pl),1);
													//*zout=(uint8_t)floor(0.49+(c/coeff));
																ADM_assert(coeff);
				ADM_assert(coeff<16);
				*zout=(c*fixMul[coeff])>>16;
				zout++;
				incur++;
				innext++;
				inprev++;	
				nl++;pl++;nc++;pc++;	  
			}
			zout+=2;
			incur+=2;
			innext+=2;
			inprev+=2;
		}
		vidCache->unlockAll();
		return 1;	
}
void DIA_working::closeDialog( void )
{
  workWindow *wind=(workWindow *)_priv; ADM_assert(wind);
    if(wind) delete wind;
    wind=NULL;
}
uint8_t		OGMDemuxer::readHeader(uint32_t *paySize, uint32_t *flags, uint64_t *frame,uint8_t *id)
{
uint8_t gotcha=0,c=0;
uint32_t total=0,failed=0;
uint64_t seq;


	*frame=0;

	if(_payload) fseeko(_fd,_payload,SEEK_CUR);
	_payload=0;
	while(1)
	{
		_hdrpos=ftello(_fd);
		if(fread(&_page,sizeof(_page),1,_fd)!=1) return 0;

		if(!fourCC::check(_page.sig,(uint8_t *)"OggS"))
		{
			printf("Bad at offset :%lu 0x %x\n",_hdrpos,_hdrpos);
			ADM_assert(0);
		}
		*id=fourCC::get(_page.serial);
		//
		
		seq=_page.page_sequence[0]+(_page.page_sequence[1]<<8);
		//printf("seq:%x \n",seq);
		uint64_t *ll;
		ll=(uint64_t *)_page.abs_pos;		
		//printf("abs:%llx \n",*ll);
		
		//
		//if(fourCC::check(_trackId,_page.serial)) // got it
		{
			gotcha=1;
		}
		total=0;
		_nbLace=_page.nb_segment;
		_nbFrag=0;
		for(uint32_t i=0;i<_page.nb_segment;i++)
		{

			c=fgetc(_fd);
			_lace[i]=c;
			if(c!=0xff) _nbFrag++;
			total+=c;
		}


		if(gotcha)
		{
#if 0		
			*frame=*(unsigned long long *)_page.abs_pos;
#else			
			*frame+=_page.abs_pos[4]+(_page.abs_pos[5]<<8)+(_page.abs_pos[6]<<16)+
					(_page.abs_pos[7]<<24);
			*frame=(*frame)<<32;
			*frame=_page.abs_pos[0]+(_page.abs_pos[1]<<8)+(_page.abs_pos[2]<<16)+
					(_page.abs_pos[3]<<24);
			if(*frame>48000*3 && seq==3)
			{
				printf("Fixing stupid abs_pos\n");
				*frame=0;
			}
			
			
#endif			
			*flags=_page.header_type;
			*paySize=total;
			_payload=total;
			return 1;
		}
		// skipt it
		fseek(_fd,total,SEEK_CUR);
		failed++;
		if(failed>10)
		{
			_payload=0;
			return 0; // we allow 10 fails
		}
	}
	return 0;
}
AVDMGenericVideoStream *getFirstCurrentVideoFilter( void)
{
	ADM_assert(nb_active_filter);
 	return videofilters[  0].filter;
}
///_____________________________________________________
/// retrieve gtkwidget through their name
/// the aim is to avoid having to modify the glade generated file
///_____________________________________________________
uint8_t  bindGUI( void )
{

#define ADM_LOOKUP(a,b) a= lookup_widget (guiRootWindow,#b);if(!a) return 0;


	ADM_LOOKUP(guiDrawingArea,guiDrawing);
	ADM_LOOKUP(guiSlider,sliderNavigate);

	sliderAdjustment=gtk_range_get_adjustment (GTK_RANGE(guiSlider));

	ADM_LOOKUP(guiMarkA,labelMarkA);
	ADM_LOOKUP(guiMarkB,labelMarkB);
	ADM_LOOKUP(guiCurFrame,boxCurFrame);
	ADM_LOOKUP(guiTotalFrame,labelTotalFrame);
	
	ADM_LOOKUP(guiCurTime,boxCurTime);
	ADM_LOOKUP(guiTotalTime,labelTotalTime);

#if 0
	ADM_LOOKUP(guiPreviewToggle,toggletoolbuttonPreview);
	ADM_LOOKUP(guiOutputToggle,toggletoolbuttonOutput);

	ADM_LOOKUP(guiAudioToggle,togglebuttonAudio);
	ADM_LOOKUP(guiVideoToggle,togglebuttonVideo);
#endif
#undef ADM_LOOKUP
  // bind menu
 #define CALLBACK(x,y) gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,#x)), "activate", \
                      GTK_SIGNAL_FUNC(guiCallback),                   (void *) y)

 	#include "GUI_menumap.h"
  #undef CALLBACK
  /// /bind menu
	
// destroy
	 gtk_object_set_data_full(GTK_OBJECT(guiRootWindow),
			     "guiRootWindow",
			     guiRootWindow,
			     (GtkDestroyNotify) destroyCallback);
	
	
//	now add callbacks
	 gtk_widget_add_events(guiRootWindow, GDK_BUTTON_PRESS_MASK);
	 gtk_signal_connect(GTK_OBJECT(guiRootWindow), "button_press_event", GTK_SIGNAL_FUNC(UI_returnFocus), NULL);

	gtk_signal_connect(GTK_OBJECT(guiSlider), "button_press_event", GTK_SIGNAL_FUNC(UI_SliderPressed), NULL);
	gtk_signal_connect(GTK_OBJECT(guiSlider), "button_release_event", GTK_SIGNAL_FUNC(UI_SliderReleased), NULL);

	// Current Frame	
	gtk_signal_connect(GTK_OBJECT(guiCurFrame), "focus_in_event", GTK_SIGNAL_FUNC(UI_grabFocus), (void *) NULL);
	gtk_signal_connect(GTK_OBJECT(guiCurFrame), "focus_out_event", GTK_SIGNAL_FUNC(UI_loseFocus), (void *) NULL);
	gtk_signal_connect(GTK_OBJECT(guiCurFrame), "activate", GTK_SIGNAL_FUNC(UI_focusAfterActivate), (void *) ACT_JumpToFrame);

    // Volume
    gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,"hscalVolume")), "value_changed", GTK_SIGNAL_FUNC(volumeChange), (void *) NULL);

    // Jog
    gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,"jogg")), "value_changed", GTK_SIGNAL_FUNC(jogChange), (void *) NULL);

	// Time Shift
	gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,"spinbuttonTimeShift")), "focus_in_event", GTK_SIGNAL_FUNC(UI_grabFocus), (void *) NULL);
	gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,"spinbuttonTimeShift")), "focus_out_event", GTK_SIGNAL_FUNC(UI_loseFocus), (void *) NULL);
	gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,"spinbuttonTimeShift")), "activate", GTK_SIGNAL_FUNC(UI_focusAfterActivate), (void *) ACT_TimeShift);

#define ADD_SIGNAL(a,b,c)  gtk_signal_connect(GTK_OBJECT(a), b, GTK_SIGNAL_FUNC(guiCallback), (void *) c);

   	ADD_SIGNAL(guiSlider,"value_changed",ACT_Scale);
	ADD_SIGNAL(lookup_widget(guiRootWindow,"spinbuttonTimeShift"),"value_changed",ACT_TimeShift);

	// Callbacks for buttons
		uint32_t nb=sizeof(buttonCallback)/sizeof(buttonCallBack_S); 
		GtkWidget *bt;
		
		
		for(uint32_t i=0;i<nb;i++)
		{
			bt= lookup_widget (guiRootWindow,buttonCallback[i].name);
			if(!bt)
			{
				printf("Binding failed for %s\n",buttonCallback[i].name);
				ADM_assert(0);
			}
			ADD_SIGNAL(bt,buttonCallback[i].signal,buttonCallback[i].action);
			GTK_WIDGET_UNSET_FLAGS (bt, GTK_CAN_FOCUS);
		}

	GTK_WIDGET_SET_FLAGS (lookup_widget(guiRootWindow,"boxCurFrame"), GTK_CAN_FOCUS);
		       
// set some tuning
    gtk_widget_set_usize(guiDrawingArea, 512, 288);
    
// hscale    
    GTK_WIDGET_UNSET_FLAGS (guiSlider, GTK_CAN_FOCUS);	
    gtk_widget_show(guiSlider);
    // And, the size now scales to the width of the window.
    gtk_widget_set_usize(guiSlider, 0, 0);
    // Plus, two-decimal precision.
    gtk_scale_set_digits(GTK_SCALE(guiSlider), 2);
    // And continuous updates!
    gtk_range_set_update_policy (GTK_RANGE (guiSlider), GTK_UPDATE_CONTINUOUS);	    

    gtk_range_set_range(GTK_RANGE(guiSlider),0,100.00);
    
    // keyboard events
    
   
 	gtk_signal_connect(GTK_OBJECT(guiDrawingArea), "expose_event",
		       GTK_SIGNAL_FUNC(on_drawingarea1_expose_event),
		       NULL);
		       
		       
	// Finally add video codec...
	uint32_t nbVid;
	const char *name;
        GtkComboBox     *combo_box;

                nbVid=encoderGetNbEncoder();
                combo_box=GTK_COMBO_BOX(lookup_widget(guiRootWindow,VIDEO_WIDGET));
                gtk_combo_box_remove_text(combo_box,0);
                printf("Found %d video encoder\n",nbVid);
                for(uint32_t i=0;i<nbVid;i++)
                {
                        name=encoderGetIndexedName(i);
                        gtk_combo_box_append_text      (combo_box,QT_TR_NOOP(name));
                }

        gtk_combo_box_set_active(combo_box,0);
        on_video_change();
        // And A codec
        // Finally add video codec...
        uint32_t nbAud;

                nbAud=audioFilterGetNbEncoder();
                combo_box=GTK_COMBO_BOX(lookup_widget(guiRootWindow,AUDIO_WIDGET));
                gtk_combo_box_remove_text(combo_box,0);
                printf("Found %d audio encoder\n",nbAud);		       
                for(uint32_t i=0;i<nbAud;i++)
                {
                        name=audioFilterGetIndexedName(i);
                        gtk_combo_box_append_text      (combo_box,QT_TR_NOOP(name));	
                }
        gtk_combo_box_set_active(combo_box,0);
	on_audio_change();
        /*   Fill in output format window */
        uint32_t nbFormat;

                nbFormat=sizeof(ADM_allOutputFormat)/sizeof(ADM_FORMAT_DESC);
                combo_box=GTK_COMBO_BOX(lookup_widget(guiRootWindow,FORMAT_WIDGET));
                gtk_combo_box_remove_text(combo_box,0);
                printf("Found %d Format \n",nbFormat);		       
                for(uint32_t i=0;i<nbFormat;i++)
                {
                        gtk_combo_box_append_text      (combo_box,QT_TR_NOOP(ADM_allOutputFormat[i].text));	
                }
        gtk_combo_box_set_active(combo_box,0);
        /* File in preview mode combobox */
            const char *previewText[]=
                {
                    QT_TR_NOOP("Input"),
                    QT_TR_NOOP("Output"),
                    QT_TR_NOOP("Side"),
                    QT_TR_NOOP("Top"),
                    QT_TR_NOOP("Separate")
                };

                combo_box=GTK_COMBO_BOX(lookup_widget(guiRootWindow,PREVIEW_WIDGET));
                gtk_combo_box_remove_text(combo_box,0);
                for(uint32_t i=0;i<sizeof(previewText)/sizeof(char*);i++)
                {
                        name=previewText[i];
                        gtk_combo_box_append_text      (combo_box,(name));	
                }
        gtk_combo_box_set_active(combo_box,0);
        // Format
                 gtk_combo_box_set_active(GTK_COMBO_BOX(lookup_widget(guiRootWindow,FORMAT_WIDGET)),0);

    //
        gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,VIDEO_WIDGET)), "changed",
                       GTK_SIGNAL_FUNC(on_video_change),
                       NULL);
        gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,AUDIO_WIDGET)), "changed",
                       GTK_SIGNAL_FUNC(on_audio_change),
                       NULL);
        gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,PREVIEW_WIDGET)), "changed",
                       GTK_SIGNAL_FUNC(on_preview_change),
                       NULL);
        gtk_signal_connect(GTK_OBJECT(lookup_widget(guiRootWindow,FORMAT_WIDGET)), "changed",
                       GTK_SIGNAL_FUNC(on_format_change),
                       NULL);
        
        // Add initial recent files
        UI_updateRecentMenu(  );
    //
    //CYB 2005.02.22: DND (START)
    // Set up avidemux as an available drag'n'drop target.
    gtk_drag_dest_set(guiRootWindow,
        GTK_DEST_DEFAULT_ALL,
        target_table,sizeof(target_table)/sizeof(GtkTargetEntry),
        (GdkDragAction)(GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_DEFAULT));
    g_signal_connect(GTK_OBJECT(guiRootWindow), "drag_data_received",
        GTK_SIGNAL_FUNC(DNDDataReceived),NULL);
    //CYB 2005.02.22: DND (END)

     // Allow shrink
   //GTK_WINDOW ( guiRootWindow ) ->allow_shrink = FALSE;
   //GTK_WINDOW ( guiDrawingArea ) ->allow_shrink = FALSE;

   // By default enable arrow keys
   UI_arrow_enabled();
  // Add custom menu
 GUI_initCustom();
    return 1;

}