Пример #1
0
//___________________________________
uint8_t  A_SaveAudioNVideo(const char *name)
{
     uint32_t needSmart=0,fl;
     GenericAviSave	*nw=NULL;
     aviInfo info;
     uint8_t ret=0;

     video_body->getVideoInfo(&info);

     printf("\n video process mode : %d",videoProcessMode());
     if (!videoProcessMode())
     {
          if(video_body->isMultiSeg()) needSmart=1;
                  video_body->getFlags(frameStart,&fl);
          if(!(fl&AVI_KEY_FRAME)) needSmart=1;

          if(needSmart) printf("\n probably need smart copy mode\n");
      
          if( !isMpeg4Compatible(  info.fcc)
                && !isMSMpeg4Compatible(info.fcc))
             {
                    printf("\n not encodable, cancelling smart mode\n");
                    needSmart=0;
               }


               int value=video_body->getEnv(ENV_EDITOR_SMART);
               nw=NULL;
               if(needSmart)
               {
                  if(value)
                  {
                     nw=new   GenericAviSaveSmart(3);
                  }
                  else
                  {
                    if(GUI_Question(QT_TR_NOOP("You may need smart copy.\n Enable it ?")))
                    {
                        value=4;
                        if( ! GUI_getIntegerValue(&value, 2, 31, "_Q factor (set 4):"))
                                      return 0;
                        nw=new   GenericAviSaveSmart(value);
                    }
                }
               }
              if(!nw)
                    nw=new   GenericAviSaveCopy;
               
       }
       else
       {

              printf("\n Process mode\n");
              nw=new   GenericAviSaveProcess;
        }
     ret=nw->saveAvi(name);
     delete nw;

return ret;
}
Пример #2
0
//_______________________________________________
uint8_t ogmSave(const char  *name)
{
uint8_t ret=0;
	ADM_ogmWrite *writter;
	if(videoProcessMode())
		writter=new ADM_ogmWriteProcess;
	else
		writter=new ADM_ogmWriteCopy;
	ret=writter->save(name);
	
	delete writter;
	return ret;
}
Пример #3
0
uint8_t oplug_mp4(const char *name, ADM_OUT_FORMAT type)
{
AVDMGenericVideoStream *_incoming=NULL;
AVDMGenericAudioStream  *audio=NULL;

uint8_t		audioBuffer[48000];
uint8_t         *videoBuffer=NULL;

uint32_t alen;//,flags;
uint32_t size;

uint8_t   ret=0;

uint32_t  sample_got=0,sample;
uint32_t  extraDataSize=0;
uint8_t   *extraData=NULL;
lavMuxer  *muxer=NULL;
aviInfo      info;
uint32_t   width,height;
DIA_encoding *encoding_gui=NULL;
Encoder         *_encode=NULL;
char            *TwoPassLogFile=NULL;
uint32_t total=0;
uint32_t videoExtraDataSize=0;
uint8_t  *videoExtraData=NULL;
uint8_t *dummy,err;
WAVHeader *audioinfo=NULL;
int prefill=0;
uint32_t displayFrame=0;
ADMBitstream    bitstream;
uint32_t        frameWrite=0;
ADM_MUXER_TYPE muxerType=MUXER_MP4;
uint8_t dualPass=0;
uint8_t r=0;
uint32_t skipping=1;
           if(type==ADM_PSP)
               muxerType=MUXER_PSP;
           else
               muxerType=MUXER_MP4;
        // Setup video
        
        if(videoProcessMode())
        {
             _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart);
        }else
        {
             _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart);
        }

           videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3];
                // Set global header encoding, needed for H264
           _encode = getVideoEncoder (_incoming->getInfo()->width,
                        _incoming->getInfo()->height,1);
           total= _incoming->getInfo()->nb_frames;

           encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000);

           if (!_encode)
                {
                  GUI_Error_HIG (_("Cannot initialize the video stream"), NULL);
                        goto  stopit;
                }

                // init compressor
                encoding_gui->setContainer("MP4");
                encoding_gui->setAudioCodec("None");
                if(!videoProcessMode())
                        encoding_gui->setCodec("Copy");
                else
                        encoding_gui->setCodec(_encode->getDisplayName());
                TwoPassLogFile=new char[strlen(name)+6];
                strcpy(TwoPassLogFile,name);
                strcat(TwoPassLogFile,".stat");
                _encode->setLogFile(TwoPassLogFile,total);

                if (!_encode->configure (_incoming))
                {
                      GUI_Error_HIG (_("Filter init failed"), NULL);
                     goto  stopit;
                };

                dualPass=_encode->isDualPass();
                if(dualPass)
                {
                       
                        if(!prepareDualPass(videoBuffer,TwoPassLogFile,encoding_gui,_encode,total))
                                goto stopit;
                }else
                {
                        encoding_gui->setPhasis ("Encoding");
                }
                
                info.width=_incoming->getInfo()->width;
                info.height=_incoming->getInfo()->height;
                info.nb_frames=_incoming->getInfo()->nb_frames;
                info.fps1000=_incoming->getInfo()->fps1000;
                info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME
                _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy);
                if(videoExtraDataSize)
                {
                        printf("We have extradata for video in copy mode (%d)\n",videoExtraDataSize);
                        videoExtraData=new uint8_t[videoExtraDataSize];
                        memcpy(videoExtraData,dummy,videoExtraDataSize);
                }
        // _________________Setup video (cont) _______________
        // ___________ Read 1st frame _________________
             
             ADM_assert(_encode);
             bitstream.data=videoBuffer;
             
preFilling:
             bitstream.cleanup(0);
             if(!(err=_encode->encode ( prefill, &bitstream)))//&len, videoBuffer, &flags,&displayFrame))
             {
                        printf("MP4:First frame error\n");
                        GUI_Error_HIG (_("Error while encoding"), NULL);
                        goto  stopit;
              }
              if(!bitstream.len)
              {
                prefill++;
                goto preFilling;
              }
              if(!bitstream.flags & AVI_KEY_FRAME)
              {
                GUI_Error_HIG (_("KeyFrame error"),_( "The beginning frame is not a key frame.\nPlease move the A marker."));
                  goto  stopit; 
              }
           //len=bitstream.len;
           // If needed get VOL header
           if(isMpeg4Compatible(info.fcc) && !videoExtraDataSize && bitstream.len)
           {
                // And put them as extradata for esds atom
                uint32_t voslen=0;
               
                if(extractVolHeader(videoBuffer,bitstream.len,&voslen))
                {
                        if(voslen)
                        {
                                videoExtraDataSize=voslen;
                                videoExtraData=new uint8_t[videoExtraDataSize];
                                memcpy(videoExtraData,videoBuffer,videoExtraDataSize);
                        }
                } else  printf("Oops should be settings data for esds\n");
            }

// ____________Setup audio__________________
          if(currentaudiostream)
          {
                audio=mpt_getAudioStream();
                if(!audio)
                {
                        GUI_Error_HIG (_("Cannot initialize the audio stream"), NULL);
                        goto  stopit;
                }
          } 
          if(audio)
          {
                audioinfo=audio->getInfo();
                audio->extraData(&extraDataSize,&extraData);
                if(audioProcessMode())
                        encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding));
                else
                         encoding_gui->setAudioCodec("Copy");

           }else
           {
                encoding_gui->setAudioCodec("None");
           }
// ____________Setup Muxer _____________________
           muxer= new lavMuxer;
           
           if(!muxer->open(
                name,
                2000000, // Muxrate
                MUXER_MP4,
                &info,videoExtraDataSize,videoExtraData,
                audioinfo,extraDataSize,extraData))
                         goto stopit;
           //_____________ Loop _____________________
          
          encoding_gui->setContainer("MP4");
          if(audio)
                encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding));
          if(!videoProcessMode())
                encoding_gui->setCodec("Copy");
          else
                encoding_gui->setCodec(_encode->getDisplayName());
           //
          if(bitstream.len)
          {
            muxer->writeVideoPacket( &bitstream);
            frameWrite++;
          }

           

           for(int frame=1;frame<total;frame++)
           {
                while(muxer->needAudio())
               {
                     if(!audio->getPacket(audioBuffer,&alen,&sample)) break;
                     if(alen)
                     {
                        muxer->writeAudioPacket(alen,audioBuffer,sample_got);
                        encoding_gui->feedAudioFrame(alen);
                        sample_got+=sample;
                     }
               }
               ADM_assert(_encode);
               bitstream.cleanup(frameWrite);
               if(!prefill || frame+prefill<total) 
               {
                  r=_encode->encode ( prefill+frame, &bitstream);
               }
                else
                {
                    r=_encode->encode ( total-1, &bitstream);
                }
               if(!r)
               {
                        printf("MP4:Frame %u error\n",frame);
                        GUI_Error_HIG (_("Error while encoding"), NULL);
                        goto  stopit;
                }
                if(!bitstream.len && skipping)
                {
                    printf("Frame skipped (xvid ?)\n");
                    continue;
                }
                skipping=0;
            //    printf("Prefill %u FrameWrite :%u Frame %u PtsFrame :%u\n",prefill,frameWrite,frame,bitstream.ptsFrame);
                frameWrite++;
                muxer->writeVideoPacket( &bitstream);

               encoding_gui->setFrame(frame,total);
               encoding_gui->feedFrame(bitstream.len);
               if(!encoding_gui->isAlive())
                {
                  if(GUI_YesNo(_("Stop Request"), _("Do you want to abort encoding ?")))
                                goto stopit;
                }
               
           }
           ret=1;
           
stopit:
           if(muxer) muxer->close();
           if(encoding_gui) delete encoding_gui;
           if(TwoPassLogFile) delete [] TwoPassLogFile;
           if(videoBuffer) delete [] videoBuffer;
           if(muxer) delete muxer;
           if(_encode) delete _encode;	
           if(videoExtraData) delete [] videoExtraData;
           // Cleanup
           deleteAudioFilter (audio);
           return ret;
}
Пример #4
0
//*************************************
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);

		}



}
Пример #5
0
/*
 * 		\fn    Oplug_flv
		\brief Main function to save in flv format.
		It is very close to oplug_mp4 but somehow simplified as the following assumptions are made :
				* No b frame
				* No 2 pass encoding

*/
uint8_t oplug_flv(const char *name)
{
AVDMGenericVideoStream *_incoming=NULL;
AVDMGenericAudioStream  *audio=NULL;

uint8_t		audioBuffer[48000];
uint8_t         *videoBuffer=NULL;

uint32_t alen;//,flags;
uint32_t size;

uint32_t  sample_got=0,sample;
uint32_t  extraDataSize=0;
uint8_t   *extraData=NULL;
lavMuxer  *muxer=NULL;
aviInfo      info;
uint32_t   width,height;
DIA_encoding *encoding_gui=NULL;
Encoder         *_encode=NULL;
uint32_t total=0;
uint32_t videoExtraDataSize=0;
uint8_t  *videoExtraData=NULL;
uint8_t *dummy,err;
WAVHeader *audioinfo=NULL;
int prefill=0;
uint32_t displayFrame=0;
ADMBitstream    bitstream(0);
uint8_t r=0;
pthread_t     audioThread;
audioQueueMT context;
PacketQueue   *pq=NULL;//("MP4 audioQ",50,2*1024*1024);
uint32_t    totalAudioSize=0;
int frameDelay = 0;
bool receivedFrame = false;

        // Setup video

        if(videoProcessMode())
        {
             _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart);
        }else
        {
             _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart);
        }

           videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3];
                // Set global header encoding, needed for H264
           _encode = getVideoEncoder (_incoming->getInfo()->width,  _incoming->getInfo()->height,1);
           total= _incoming->getInfo()->nb_frames;

           info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME
           //
           int supported=0;
           if(isVP6Compatible(info.fcc)) supported=1;
           if(fourCC::check(info.fcc,(const uint8_t *)"FLV1")) supported=1;
           if(!supported)
           {
        	   GUI_Error_HIG(QT_TR_NOOP("Unsupported video"),QT_TR_NOOP("Only FLV1 and VP6 video are supported"));
        	   goto stopit;
           }
           /* Check audio, we support only mp3 right now
            * 44100, 22050, 11025 only!
            *  */
           if(currentaudiostream)
           {
        	   uint32_t audioCodec=0;
        	   uint32_t fq=currentaudiostream->getInfo()->frequency;

        	   	if(audioProcessMode())
        	   	{
        	   		audioCodec=audioFilter_getOuputCodec();
        	   		fq=audioFilter_getOuputFrequency(fq);

        	   	}else
        	   	{	// copy
        	   		audioCodec=currentaudiostream->getInfo()->encoding;
        	   	}
        	   	if(audioCodec!=WAV_MP3 )
        	   		{
        	   			GUI_Error_HIG(QT_TR_NOOP("Unsupported audio"),QT_TR_NOOP("Audio must be mp3 for flv output."));
        	   			goto stopit;
        	   		}
        	   	if(fq!=44100 && fq!=22050 && fq!=11025)
        	   	{
    	   			GUI_Error_HIG(QT_TR_NOOP("Unsupported audio"),QT_TR_NOOP("Frequency must be 44100, 22050 or 11025 Hz."));
    	   			goto stopit;

        	   	}
           }


           encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000);
           bitstream.bufferSize=_incoming->getInfo()->width*_incoming->getInfo()->height*3;
           if (!_encode)
                {
                  GUI_Error_HIG ("[FLV]",QT_TR_NOOP("Cannot initialize the video stream"));
                        goto  stopit;
                }

                // init compressor
                encoding_gui->setContainer(QT_TR_NOOP("FLV"));
                encoding_gui->setAudioCodec(QT_TR_NOOP("None"));
                if(!videoProcessMode())
                        encoding_gui->setCodec(QT_TR_NOOP("Copy"));
                else
                        encoding_gui->setCodec(_encode->getDisplayName());

                if (!_encode->configure (_incoming))
                {
                      GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL);
                     goto  stopit;
                };

                encoding_gui->setPhasis (QT_TR_NOOP("Encoding"));


                info.width=_incoming->getInfo()->width;
                info.height=_incoming->getInfo()->height;
                info.nb_frames=_incoming->getInfo()->nb_frames;
                info.fps1000=_incoming->getInfo()->fps1000;

                _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy);
                if(videoExtraDataSize)
                {
                        printf("[FLV]We have extradata for video in copy mode (%d)\n",videoExtraDataSize);
                        videoExtraData=new uint8_t[videoExtraDataSize];
                        memcpy(videoExtraData,dummy,videoExtraDataSize);
                }

             ADM_assert(_encode);
             bitstream.data=videoBuffer;

// ____________Setup audio__________________
          if(currentaudiostream)
          {
                audio=mpt_getAudioStream();
                if(!audio)
                {
                        GUI_Error_HIG ("[FLV]",QT_TR_NOOP("Cannot initialize the audio stream"));
                        goto  stopit;
                }
          }
          if(audio)
          {
                audioinfo=audio->getInfo();
                audio->extraData(&extraDataSize,&extraData);
                if(audioProcessMode())
                        encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding));
                else
                         encoding_gui->setAudioCodec(QT_TR_NOOP("Copy"));

           }else
           {
                encoding_gui->setAudioCodec(QT_TR_NOOP("None"));
           }
// ____________Setup Muxer _____________________
           muxer= new lavMuxer;

           if(!muxer->open(
                name,
                2000000, // Muxrate
                MUXER_FLV,
                &info,videoExtraDataSize,videoExtraData,
                audioinfo,extraDataSize,extraData))
                         goto stopit;
//_____________ Loop _____________________

          encoding_gui->setContainer(QT_TR_NOOP("FLV"));

          if(!videoProcessMode())
                encoding_gui->setCodec(QT_TR_NOOP("Copy"));
          else
                encoding_gui->setCodec(_encode->getDisplayName());
           //
          UI_purge();

//_____________ Start Audio thread _____________________
          if(audio)
          {
            pq=new PacketQueue("[FLV] audioQ",5000,2*1024*1024);
            memset(&context,0,sizeof(context));
            context.audioEncoder=audio;
            context.audioTargetSample=0xFFFF0000; ; //FIXME
            context.packetQueue=pq;
            // start audio thread
            ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context));
            ADM_usleep(4000);
          }
//_____________GO !___________________

			 for (uint32_t frame = 0; frame < total; frame++)
			 {
				 if (!encoding_gui->isAlive())
				 {
					 r = 0;
					 break;
				 }

				 while(muxer->needAudio())
				 {
					 if(pq->Pop(audioBuffer,&alen,&sample))
					 {
						 if(alen)
						 {
							 muxer->writeAudioPacket(alen,audioBuffer,sample_got);
							 totalAudioSize+=alen;
							 encoding_gui->setAudioSize(totalAudioSize);
							 sample_got+=sample;
						 }
					 }
					 else
					 {
						 r = 0;
						 break;
					 }
				 }

				 for (;;)
				 {
					 bitstream.cleanup(frame);

					 if (frame + frameDelay >= total)
					 {
						 if (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH)
							 r = _encode->encode(UINT32_MAX, &bitstream);
						 else
							 r = 0;
					 }
					 else
						 r = _encode->encode(frame + frameDelay, &bitstream);

					 if (!r)
					 {
						 printf("Encoding of frame %lu failed!\n", frame);
						 GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL);
						 break;
					 }
					 else if (!receivedFrame && bitstream.len > 0)
					 {
						 if (!(bitstream.flags & AVI_KEY_FRAME))
						 {
							 GUI_Error_HIG (QT_TR_NOOP("KeyFrame error"), QT_TR_NOOP("The beginning frame is not a key frame.\nPlease move the A marker."));
							 r = 0;
							 break;
						 }
						 else
							 receivedFrame = true;
					 }

					 if (bitstream.len == 0 && (_encode->getRequirements() & ADM_ENC_REQ_NULL_FLUSH))
					 {
						 printf("skipping frame: %u size: %i\n", frame + frameDelay, bitstream.len);
						 frameDelay++;
					 }
					 else
						 break;
				 }

				 if (!r)
					 break;

				 muxer->writeVideoPacket(&bitstream);
				 encoding_gui->setFrame(frame, bitstream.len, bitstream.out_quantizer, total);
			 }

stopit:

    // Flush slave Q
    if(audio&& pq)
    {
        context.audioAbort=1;
        pq->Abort();
        // Wait for audio slave to be over
        while(!context.audioDone)
        {
          printf("[FLV]Waiting Audio thread\n");
          ADM_usleep(500000);
        }
        delete pq;
    }
    //
           if(muxer) muxer->close();
           if(encoding_gui) delete encoding_gui;
           if(videoBuffer) delete [] videoBuffer;
           if(muxer) delete muxer;
           if(_encode) delete _encode;
           if(videoExtraData) delete [] videoExtraData;
           // Cleanup
           deleteAudioFilter (audio);
           return r;
}
Пример #6
0
uint8_t oplug_mp4(const char *name, ADM_OUT_FORMAT type)
{
AVDMGenericVideoStream *_incoming=NULL;
AVDMGenericAudioStream  *audio=NULL;

uint8_t		audioBuffer[48000];
uint8_t         *videoBuffer=NULL;

uint32_t alen;//,flags;
uint32_t size;

uint8_t   ret=0;

uint32_t  sample_got=0,sample;
uint32_t  extraDataSize=0;
uint8_t   *extraData=NULL;
lavMuxer  *muxer=NULL;
aviInfo      info;
uint32_t   width,height;
DIA_encoding *encoding_gui=NULL;
Encoder         *_encode=NULL;
char            *TwoPassLogFile=NULL;
uint32_t total=0;
uint32_t videoExtraDataSize=0;
uint8_t  *videoExtraData=NULL;
uint8_t *dummy,err;
WAVHeader *audioinfo=NULL;
int prefill=0;
uint32_t displayFrame=0;
ADMBitstream    bitstream(0);
uint32_t        frameWrite=0;
ADM_MUXER_TYPE muxerType=MUXER_MP4;
uint8_t dualPass=0;
uint8_t r=0;
uint32_t skipping=1;
pthread_t     audioThread;
audioQueueMT context;
PacketQueue   *pq;//("MP4 audioQ",50,2*1024*1024);
uint32_t    totalAudioSize=0;
uint32_t sent=0;
const char *containerTitle;
           switch(type)
           {
             case ADM_PSP:muxerType=MUXER_PSP;containerTitle="PSP";break;
             case ADM_MP4:muxerType=MUXER_MP4;containerTitle="MP4";break;
             case ADM_MATROSKA:muxerType=MUXER_MATROSKA;containerTitle="MKV";break;
             default:
                ADM_assert(0);
           }
        // Setup video
        
        if(videoProcessMode())
        {
             _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart);
        }else
        {
             _incoming = getFirstVideoFilter (frameStart,frameEnd-frameStart);
        }

           videoBuffer=new uint8_t[_incoming->getInfo()->width*_incoming->getInfo()->height*3];
                // Set global header encoding, needed for H264
           _encode = getVideoEncoder (_incoming->getInfo()->width,
                        _incoming->getInfo()->height,1);
           total= _incoming->getInfo()->nb_frames;

           encoding_gui=new DIA_encoding(_incoming->getInfo()->fps1000);
           bitstream.bufferSize=_incoming->getInfo()->width*_incoming->getInfo()->height*3;
           if (!_encode)
                {
                  GUI_Error_HIG (QT_TR_NOOP("Cannot initialize the video stream"), NULL);
                        goto  stopit;
                }

                // init compressor
               
                  encoding_gui->setContainer(containerTitle);
               
                encoding_gui->setAudioCodec("None");
                if(!videoProcessMode())
                        encoding_gui->setCodec("Copy");
                else
                        encoding_gui->setCodec(_encode->getDisplayName());
                TwoPassLogFile=new char[strlen(name)+6];
                strcpy(TwoPassLogFile,name);
                strcat(TwoPassLogFile,".stat");
                _encode->setLogFile(TwoPassLogFile,total);

                if (!_encode->configure (_incoming))
                {
                      GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL);
                     goto  stopit;
                };

                dualPass=_encode->isDualPass();
                if(dualPass)
                {
                       
                        if(!prepareDualPass(bitstream.bufferSize,videoBuffer,TwoPassLogFile,encoding_gui,_encode,total))
                                goto stopit;
                }else
                {
                        encoding_gui->setPhasis ("Encoding");
                }
                
                info.width=_incoming->getInfo()->width;
                info.height=_incoming->getInfo()->height;
                info.nb_frames=_incoming->getInfo()->nb_frames;
                info.fps1000=_incoming->getInfo()->fps1000;
                info.fcc=*(uint32_t *)_encode->getCodecName(); //FIXME
                _encode->hasExtraHeaderData( &videoExtraDataSize,&dummy);
                if(videoExtraDataSize)
                {
                        printf("We have extradata for video in copy mode (%d)\n",videoExtraDataSize);
                        videoExtraData=new uint8_t[videoExtraDataSize];
                        memcpy(videoExtraData,dummy,videoExtraDataSize);
                }
        // _________________Setup video (cont) _______________
        // ___________ Read 1st frame _________________
             
             ADM_assert(_encode);
             bitstream.data=videoBuffer;
             
preFilling:
             bitstream.cleanup(0);
             if(!(err=_encode->encode ( prefill, &bitstream)))//&len, videoBuffer, &flags,&displayFrame))
             {
                        printf("MP4:First frame error\n");
                        GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL);
                        goto  stopit;
              }
              sent++;
              if(!bitstream.len)
              {
                prefill++;
                goto preFilling;
              }
              printf("Pass 2 prefill : %u\n",prefill);
              if(!bitstream.flags & AVI_KEY_FRAME)
              {
                GUI_Error_HIG (QT_TR_NOOP("KeyFrame error"),QT_TR_NOOP( "The beginning frame is not a key frame.\nPlease move the A marker."));
                  goto  stopit; 
              }
           //len=bitstream.len;
           // If needed get VOL header
           if(isMpeg4Compatible(info.fcc) && !videoExtraDataSize && bitstream.len)
           {
                // And put them as extradata for esds atom
                uint32_t voslen=0;
               
                if(extractVolHeader(videoBuffer,bitstream.len,&voslen))
                {
                        if(voslen)
                        {
                                videoExtraDataSize=voslen;
                                videoExtraData=new uint8_t[videoExtraDataSize];
                                memcpy(videoExtraData,videoBuffer,videoExtraDataSize);
                        }
                } else  printf("Oops should be settings data for esds\n");
            }

// ____________Setup audio__________________
          if(currentaudiostream)
          {
                audio=mpt_getAudioStream();
                if(!audio)
                {
                        GUI_Error_HIG (QT_TR_NOOP("Cannot initialize the audio stream"), NULL);
                        goto  stopit;
                }
          } 
          if(audio)
          {
                audioinfo=audio->getInfo();
                audio->extraData(&extraDataSize,&extraData);
                if(audioProcessMode())
                        encoding_gui->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding));
                else
                         encoding_gui->setAudioCodec("Copy");

           }else
           {
                encoding_gui->setAudioCodec("None");
           }
// ____________Setup Muxer _____________________
           muxer= new lavMuxer;
           
           if(!muxer->open(
                name,
                2000000, // Muxrate
                muxerType,
                &info,videoExtraDataSize,videoExtraData,
                audioinfo,extraDataSize,extraData))
                         goto stopit;
//_____________ Loop _____________________
          
          encoding_gui->setContainer(containerTitle);
         
          if(!videoProcessMode())
                encoding_gui->setCodec("Copy");
          else
                encoding_gui->setCodec(_encode->getDisplayName());
           //
          UI_purge();
          if(bitstream.len)
          {
            muxer->writeVideoPacket( &bitstream);
            frameWrite++;
          }
//_____________ Start Audio thread _____________________
          if(audio)
          {          
            pq=new PacketQueue("MP4 audioQ",5000,2*1024*1024);
            memset(&context,0,sizeof(context));
            context.audioEncoder=audio;
            context.audioTargetSample=0xFFFF0000; ; //FIXME
            context.packetQueue=pq;
            // start audio thread
            ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context)); 
            ADM_usleep(4000);
          }
//_____________GO !___________________
           for(int frame=1;frame<total;frame++)
           {
               while(muxer->needAudio())
               {
                    if(pq->Pop(audioBuffer,&alen,&sample))
                    {
                     if(alen)
                     {
                        muxer->writeAudioPacket(alen,audioBuffer,sample_got);
                        totalAudioSize+=alen;
                        encoding_gui->setAudioSize(totalAudioSize);
                        sample_got+=sample;
                     }
                    }else break;
               }
               ADM_assert(_encode);
               bitstream.cleanup(frameWrite);
               if(!prefill || frame+prefill<total) 
               {
                  
                  r=_encode->encode ( prefill+frame, &bitstream);
               }
                else
                {
                    r=_encode->encode ( total-1, &bitstream);
                }
               if(!r && frame<total-2)
               {
                        printf("MP4:Frame %u error\n",frame);
                        GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL);
                        goto  stopit;
                }
                if(!bitstream.len && skipping)
                {
                    printf("Frame skipped (xvid ?)\n");
                    continue;
                }
                sent++;
                skipping=0;
            //    printf("Prefill %u FrameWrite :%u Frame %u PtsFrame :%u\n",prefill,frameWrite,frame,bitstream.ptsFrame);
                frameWrite++;
                muxer->writeVideoPacket( &bitstream);
                encoding_gui->setFrame(frame,bitstream.len,bitstream.out_quantizer,total);
               if(!encoding_gui->isAlive())
                {
                    
                    goto stopit;
                }
               
           }
           ret=1;
           
stopit:
    printf("2nd pass, sent %u frames\n",sent);
    // Flush slave Q
    if(audio)
    {
        context.audioAbort=1;
        pq->Abort();
        // Wait for audio slave to be over
        while(!context.audioDone)
        {
          printf("Waiting Audio thread\n");
          ADM_usleep(500000); 
        }
        delete pq;
    }
    //
           if(muxer) muxer->close();
           if(encoding_gui) delete encoding_gui;
           if(TwoPassLogFile) delete [] TwoPassLogFile;
           if(videoBuffer) delete [] videoBuffer;
           if(muxer) delete muxer;
           if(_encode) delete _encode;	
           if(videoExtraData) delete [] videoExtraData;
           // Cleanup
           deleteAudioFilter (audio);
           return ret;
}
Пример #7
0
int A_Save(const char *name)
{
uint32_t end;
int ret=0;
	// depending on the type we save a avi, a mpeg or a XVCD
	CodecFamilty family;
	family= videoCodecGetFamily();
	// in case of copy mode, we stick to avi file format
	if(!videoProcessMode())
	{
		family=CodecFamilyAVI;
		if( UI_GetCurrentFormat()==ADM_PS ||UI_GetCurrentFormat()==ADM_TS )  // exception
		{
			family=CodecFamilyMpeg;
		}
                        
	}
        else
        {
                if(UI_GetCurrentFormat()==ADM_AVI_DUAL)
                {
                  GUI_Error_HIG(QT_TR_NOOP("Dual audio can only be used in copy mode"),QT_TR_NOOP( "Select Copy as the video codec."));
                        return 0;
                }
        }
	printf("**saving:**\n");
	// Check if we need to do a sanity B frame check
	if(!videoProcessMode())
	{	
		uint32_t pb;
		end=avifileinfo->nb_frames;
		// if the last frame is the last frame (!)
		// we add one to keep it, else we systematically skip
		// the last frame
#if 0					
		if(frameEnd==end-1) end=frameEnd+1;
		else
			end=frameEnd;

		if(!video_body->sanityCheckRef(frameStart,end,&pb))
		{
			if(pb)
			{
				GUI_Error_HIG("Cannot save the file", "The video starts/ends with a lonely B-frame. Please remove it.");
				return 0;
			}
			if(!GUI_Question("Warning !\n Bframe has lost its reference frame\nContinue ?"))
				return 0;
		}
#endif
		// Alter frameEnd so that it is not a B frame	
		// as frameEnd -1 position	
		uint32_t tgt=frameEnd;;
		uint32_t flag=0,found=0;
		
		// need to do something ?
		if(frameEnd>frameStart)
		{
			tgt=frameEnd;
			if(tgt==end-1) tgt++;
			video_body->getFlags(tgt-1,&flag);
			if((frameEnd&AVI_B_FRAME))
			{
				printf("Last frame is a B frame, choosing better candidate\n");
				 // The last real one is not a I/P Frame
				 // Go forward or rewind
				 if(tgt<end-1)
				{	// Try next if possible
					video_body->getFlags(tgt,&flag);
					if(!(flag&AVI_B_FRAME))
					{
						printf("Taking next frame as last frame %lu\n",tgt+1);
				 		frameEnd=tgt+1;
				 		found=1;
					}
				}
				if(!found) // next frame not possible, rewind
				{
					if(tgt>=end-2) tgt=end-2;
					while(tgt>frameStart)
					{
						printf("Trying :%lu\n",tgt);
						video_body->getFlags(tgt,&flag);
						if(!(flag&AVI_B_FRAME))
						{
							printf("Taking previous frame as last frame %lu\n",tgt+1);
				 			frameEnd=tgt+1;
				 			found=1;
							break;
						}
						else tgt--;
					}
				}
				ADM_assert(found);
			}
		}
		
		
		
	}
        printf("Output format:%d\n",UI_GetCurrentFormat());
	switch(family)
	{
		case CodecFamilyAVI:
					printf(" AVI family\n");
					switch(UI_GetCurrentFormat())
					{
						case ADM_DUMMY:
					                            			ret=oplug_dummy(name);
					                            			break;
						case ADM_FLV:
                            			ret=oplug_flv(name);
                            			break;
                        case ADM_MP4:
                        case ADM_PSP:
                        case ADM_MATROSKA:
                        
                                                    ret=oplug_mp4(name,UI_GetCurrentFormat());
                                                    break;
						case ADM_AVI:
								ret=A_SaveAudioNVideo(name);
								break;
						case ADM_OGM:
								ret=ogmSave(name);
								break;
						case ADM_ES:
								ret=ADM_saveRaw(name);
								break;
						case ADM_AVI_DUAL:
								ret=A_SaveAudioDualAudio(name);
								break;
                                                case ADM_AVI_PAK:
								ret=A_SavePackedVop(name);
								break;

						case ADM_AVI_UNP:
								ret=A_SaveUnpackedVop(name);
								break;
						default:
                                                  GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL);
					}
					break;
		case CodecFamilyMpeg:
					printf(" MPEG family\n");
					if(!videoProcessMode())
					{
						
						printf("Using pass through\n");
                                                switch(UI_GetCurrentFormat())
                                                {
                                                  case ADM_PS:
                                                  case ADM_TS:
						          ret=mpeg_passthrough(name,UI_GetCurrentFormat());
                                                          break;
                                                  default:
                                                    GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL);
                                                }
                                                break;
                                        } // THERE IS NO BREAK HERE, NOT A MISTAKE!
		case CodecFamilyXVCD:
                    switch(UI_GetCurrentFormat())
                    {
                        case ADM_TS:
                        case ADM_PS:
                        case ADM_ES:
                                ret=oplug_mpegff(name,UI_GetCurrentFormat());;
                                break;
                        default:
                          GUI_Error_HIG(QT_TR_NOOP("Incompatible output format"), NULL);
                    }
                    break;
                default:
                            ADM_assert(0);
                            return 0;
        }
        getFirstVideoFilter(0,avifileinfo->nb_frames);
        return ret;
}
Пример #8
0
void calculatorDialog::update(void)
{
    unsigned int track1, track2;
    uint32_t audioSize;
    uint32_t totalSize;
    aviInfo info;

    video_body->getVideoInfo(&info);

    track1 = ui.audioTrack1SpinBox->value();
    track2 = ui.audioTrack2SpinBox->value();

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

    ui.audioSizeLabel->setText(QString("%1").arg(audioSize));

    // Compute total size
    unsigned int s74, s80, dvd;
    int formatIndex = ui.formatComboBox->currentIndex();

    if (formatIndex == 2)
    {
        // Mpeg
        s74 = 730;
        s80 = 790;
        dvd = 4300;
    }
    else
    {
        //AVI or OGM
        s74 = 650;
        s80 = 700;
        dvd = 4300;
    }

    int mediumIndex = ui.mediumComboBox->currentIndex();

    switch(mediumIndex)
    {
    case 0:
        totalSize = s80;
        break;
    case 1:
        totalSize = 2 * s80;
        break;
    case 2:
        totalSize = s74;
        break;
    case 3:
        totalSize= 2 * s74;
        break;
    case 4:
        totalSize = dvd;
        break;
    case 5:
        totalSize = ui.customSizeSpinBox->value();
        break;
    }

    ui.totalSizeLabel->setText(QString("%1").arg(totalSize));

    // Compute muxing overhead size
    unsigned int muxingOverheadSize;
    int numberOfAudioTracks = 0;
    int numberOfChunks;

    switch (formatIndex)
    {
    case 0:
        // AVI
        // Muxing overhead is 8 + 32 = 40 bytes per chunk.
        // More or less: numberOfChunks = (x + 1) * _videoFrameCount,
        // where x - the number of audio tracks
        if (track1 != 0)
            numberOfAudioTracks++;

        if (track2 != 0)
            numberOfAudioTracks++;

        numberOfChunks = (numberOfAudioTracks + 1) * _videoFrameCount;
        muxingOverheadSize = (unsigned int)ceil((numberOfChunks * 40) / 1048576.0);
        break;
    case 1:
        // OGM
        // Muxing overhead is 1.1% to 1.2% of (videoSize + audioSize)
        muxingOverheadSize = (unsigned int)ceil(totalSize - totalSize / 1.012);
        break;
    case 2:
        // MPEG
        // Muxing overhead is 1% to 2% of (videoSize + audioSize)
        muxingOverheadSize = (unsigned int)ceil(totalSize - totalSize / 1.02);
        break;
    }

    unsigned int videoSize = 0;

    // and compute
    if (audioSize + muxingOverheadSize >= totalSize)
        videoSize = 0;
    else
        videoSize = totalSize - audioSize - muxingOverheadSize;

    unsigned int picSize;

    // Compute average bps
    float avg;
    float bpp;

    avg = (videoSize * 1024. * 1024.) / _videoDuration;

    // now we have byte /sec, convert to kb per sec
    avg = (avg * 8) / 1000;
    ui.videoBitrateLabel->setText(QString("%1").arg((unsigned int)avg));
    ui.videoSizeLabel->setText(QString("%1").arg(videoSize));

    // Bpp
    bpp = avg * 1000000.;  // kbit->bit + compensate for fps1000

    // Fetch info from filter
    if(videoProcessMode())
        picSize = getPictureSize();
    else
        picSize = info.width * info.height;

    bpp = (bpp / picSize) / info.fps1000;

    ui.bppLabel->setText(QString("%1").arg(bpp, 0, 'g', 3));
}