/** \fn saveAsJpg \brief save current image into filename, into jpg format */ uint8_t ADMImage::saveAsJpg(const char *filename) { ffmpegEncoderFFMjpeg *codec=NULL; FILE *fd; uint8_t *buffer=NULL; uint32_t sz; sz = _width*_height*3; ADMBitstream bitstream(sz); buffer=new uint8_t[sz]; bitstream.data=buffer; codec=new ffmpegEncoderFFMjpeg(_width,_height,FF_MJPEG) ; codec->init( 95,25000); if(!codec->encode(this,&bitstream)) { GUI_Error_HIG(QT_TR_NOOP("Cannot encode the frame"), NULL); delete [] buffer; delete codec; return 0; } delete codec; fd=fopen(filename,"wb"); if(!fd) { GUI_Error_HIG(QT_TR_NOOP("File error"),QT_TR_NOOP( "Cannot open \"%s\" for writing."), filename); delete [] buffer; return 0; } fwrite (buffer, bitstream.len, 1, fd); fclose(fd); delete [] buffer; return 1; }
static inline void emulateSingleFrameBroadcastTransfer(CanDriver& can, uavcan::NodeID node_id, const MessageType& message, uavcan::TransferID tid) { uavcan::StaticTransferBuffer<100> buffer; uavcan::BitStream bitstream(buffer); uavcan::ScalarCodec codec(bitstream); // Manual message publication ASSERT_LT(0, MessageType::encode(message, codec)); ASSERT_GE(8, buffer.getMaxWritePos()); // DataTypeID data_type_id, TransferType transfer_type, NodeID src_node_id, NodeID dst_node_id, // uint_fast8_t frame_index, TransferID transfer_id, bool last_frame uavcan::Frame frame(MessageType::DefaultDataTypeID, uavcan::TransferTypeMessageBroadcast, node_id, uavcan::NodeID::Broadcast, tid); frame.setStartOfTransfer(true); frame.setEndOfTransfer(true); ASSERT_EQ(buffer.getMaxWritePos(), frame.setPayload(buffer.getRawPtr(), buffer.getMaxWritePos())); uavcan::CanFrame can_frame; ASSERT_TRUE(frame.compile(can_frame)); can.pushRxToAllIfaces(can_frame); }
//___________________________________________________ uint8_t ADM_ogmWriteProcess::writeVideo(uint32_t frame) { uint32_t len,flags; uint8_t ret; uint32_t page=_incoming->getInfo ()->width*_incoming->getInfo ()->height; ADMBitstream bitstream(page*3); bitstream.data=_videoBuffer; ret= _encode->encode ( frame, &bitstream); if(!bitstream.len && _prestoring) { printf("Frame skipped\n"); _prestore++; return 1; } _prestoring=0; bitstream.dtsFrame=frame-_prestore; if(!ret) { printf("OgmWrite: Error encoding frame %d\n",frame); return 0; } encoding_gui->setFrame(frame,bitstream.len,bitstream.out_quantizer,_togo); return videoStream->write(bitstream.len,_videoBuffer,bitstream.flags,bitstream.dtsFrame); }
void GeneralUtils::configureFabric(std::vector<char> const &buffer) { if (GeneralUtils::fileExists("/dev/xdevcfg")) { //We are on Kernel 4.6 or lower FILE *fd = fopen("/dev/xdevcfg", "w"); if (fd == NULL) { throw std::runtime_error("Could not open /dev/xdevcfg device"); } size_t written = fwrite(buffer.data(), sizeof(char), buffer.size(), fd); if (written != buffer.size()) { throw std::runtime_error("Could not write complete bitstream to /dev/xdevcfg"); } fclose(fd); } else if (GeneralUtils::fileExists("/sys/class/fpga_manager/fpga0/firmware")) { const char bitstreamFile[] = "fabric_bitstream.bin"; std::ofstream bitstream(std::string("/lib/firmware/") + bitstreamFile, std::ios::out | std::ios::binary | std::ios::trunc); bitstream.write(buffer.data(), buffer.size()); bitstream.close(); std::ofstream firmware("/sys/class/fpga_manager/fpga0/firmware"); firmware << bitstreamFile; firmware.close(); if (!firmware.good()) { throw std::runtime_error("Fabric configuration through fpga_manager failed!"); } // Loading was successful, wait for half a second before using the fpga! // or else the board is gone... praise the fpga_manager std::this_thread::sleep_for(std::chrono::milliseconds(500)); } else { // TODO load AWS bitstream } }
uint8_t oplug_mpegff(const char *name, ADM_OUT_FORMAT type) { AVDMGenericVideoStream *_incoming; Encoder *encoder=NULL; ADMMpegMuxer *muxer=NULL; FILE *file=NULL; uint8_t audioBuffer[48000]; uint32_t audioLen=0; uint32_t _w,_h,_fps1000,_page,total; AVDMGenericAudioStream *audio=NULL; 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; DIA_encoding *encoding; int reuse = 0; twoPass=new char[strlen(name)+6]; twoFake=new char[strlen(name)+6]; strcpy(twoPass,name); strcat(twoPass,".stat"); 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(QT_TR_NOOP("There is no audio track"), NULL); goto finishvcdff; } audio=mpt_getAudioStream(); mux=MUXER_TS; break; case ADM_PS: { if(!currentaudiostream) { GUI_Error_HIG(QT_TR_NOOP("There is no audio track"), NULL); goto finishvcdff; } 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(QT_TR_NOOP("Audio track is not suitable"), NULL); goto finishvcdff; } // Check WAVHeader *hdr=audio->getInfo(); audio_encoding=hdr->encoding; if (videoCodecGetType() == CodecXVCD || videoCodecGetType() == CodecVCD) { if(hdr->frequency!=44100 || hdr->encoding != WAV_MP2) { GUI_Error_HIG(("Incompatible audio"),QT_TR_NOOP( "For VCD, audio must be 44.1 kHz MP2.")); goto finishvcdff; } 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)) { GUI_Error_HIG(QT_TR_NOOP("Incompatible audio"), QT_TR_NOOP("For DVD, audio must be 48 kHz MP2, AC3 or LPCM.")); goto finishvcdff; } mux=MUXER_DVD; printf("X*VCD: Using DVD PS\n"); } } } } // Create muxer switch (videoCodecGetType()) { 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->isDualPass()) { printf("Verifying log file\n"); if (encoder->verifyLog(twoPass, total) && GUI_Question(QT_TR_NOOP("Reuse the existing log file?"))) reuse = 1; } if(!encoder->configure(_incoming, reuse)) goto finishvcdff; _buffer=new uint8_t[_page]; // Might overflow if _page only _outbuffer=new uint8_t[_page]; ADM_assert( _buffer); ADM_assert( _outbuffer); encoding =new DIA_encoding(_fps1000); switch (videoCodecGetType()) { case CodecVCD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc VCD")); break; case CodecSVCD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc SVCD")); break; case CodecDVD: encoding->setCodec(QT_TR_NOOP("libmpeg2enc DVD")); break; case CodecXVCD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-1 VBR")); break; case CodecXSVCD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-2 SVCD VBR")); break; case CodecXDVD: encoding->setCodec(QT_TR_NOOP("FFmpeg MPEG-2 DVD VBR")); break; case CodecRequant: encoding->setCodec(QT_TR_NOOP("MPEG Requantizer")); break; default: ADM_assert(0); } switch(mux) { case MUXER_NONE:encoding->setContainer(QT_TR_NOOP("MPEG ES"));break; case MUXER_TS: encoding->setContainer(QT_TR_NOOP("MPEG TS"));break; case MUXER_VCD: encoding->setContainer(QT_TR_NOOP("MPEG VCD"));break; case MUXER_SVCD:encoding->setContainer(QT_TR_NOOP("MPEG SVCD"));break; case MUXER_DVD: encoding->setContainer(QT_TR_NOOP("MPEG DVD"));break; default: ADM_assert(0); } // pass 1 if(encoder->isDualPass()) //Cannot be requant { if(!reuse) { encoding->setPhasis (QT_TR_NOOP("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(QT_TR_NOOP("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())) { printf("Muxer init failed\n"); goto finishvcdff; } 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(QT_TR_NOOP("File error"), QT_TR_NOOP("Cannot open \"%s\" for writing."), name); goto finishvcdff; } } if(encoder->isDualPass()) encoding->setPhasis (QT_TR_NOOP("Pass 2/2")); else encoding->setPhasis (QT_TR_NOOP("Encoding")); // Set info for audio if any if(muxer) { if(!audioProcessMode()) encoding->setAudioCodec(QT_TR_NOOP("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; 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; accessMutex.unlock(); goto finishvcdff; } accessMutex.unlock(); ADM_usleep(1000*1000); } } //********************************************************** // NOT MULTITHREADED //********************************************************** bitstream.data=_outbuffer; bitstream.bufferSize=_page; 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(QT_TR_NOOP("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 ()) 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; if (audio) deleteAudioFilter(audio); return ret; }
uint8_t mpeg_passthrough(const char *name,ADM_OUT_FORMAT format ) { uint32_t len, flags; AVDMGenericAudioStream *audio=NULL; uint32_t audiolen; DIA_encoding *work; ADM_MUXER_TYPE mux; double total_wanted=0; uint32_t total_got=0; uint8_t ret=0; ADMMpegMuxer *muxer=NULL; ADMBitstream bitstream(0); printf("Saving as mpg PS to file %s\n",name); // First we check it is mpeg if(!isMpeg12Compatible(avifileinfo->fcc)) { GUI_Error_HIG(QT_TR_NOOP("This is not MPEG compatible"), QT_TR_NOOP("You can't use the Copy codec.")); return 0 ; } if(!currentaudiostream) { GUI_Error_HIG(QT_TR_NOOP("There is no audio track"), NULL); return 0; } ADM_assert (video_body->getFlags (frameStart, &flags)); if(!(flags&AVI_KEY_FRAME)) { GUI_Error_HIG(QT_TR_NOOP("The first frame is not intra frame"), QT_TR_NOOP("Use the << and the >> buttons to move using Intra frames.")); 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(QT_TR_NOOP("Audio track is not suitable"), NULL); return 0; } // Check WAVHeader *hdr=audio->getInfo(); uint32_t isMpeg1; uint32_t isLav; if(!prefs->get(FEATURE_USE_LAVCODEC_MPEG2, &isLav)) { isLav=0; } if(!isLav) { decoderMpeg *mpeghdr; mpeghdr=(decoderMpeg *)video_body->rawGetDecoder(0); isMpeg1=mpeghdr->isMpeg1(); } else { // How to know if it is mpeg 1? // Assume it is not /* decoderFFMpeg12 *mpeghdr; mpeghdr=(decoderFFMpeg12 *)video_body->rawGetDecoder(0); isMpeg1=mpeghdr->isMpeg1(); */ isMpeg1=0; } switch(format) { case ADM_PS: if(isMpeg1) { if(hdr->frequency!=44100 || hdr->encoding != WAV_MP2) { GUI_Error_HIG(QT_TR_NOOP("Incompatible audio"), QT_TR_NOOP("For VCD, audio must be 44.1 kHz MP2.")); return 0 ; } mux=MUXER_VCD; printf("PassThrough: Using VCD PS\n"); }else { // Mpeg2 aviInfo info; video_body->getVideoInfo(&info); if(hdr->frequency==44100 && info.width==480&& hdr->encoding == WAV_MP2 ) // SVCD ? { mux=MUXER_SVCD; printf("PassThrough: Using SVCD PS\n"); } else { uint32_t valid=0; if(!prefs->get(FEATURE_MPEG_NO_LIMIT,&valid)) valid=0; // mpeg2, we do only DVD right now if(hdr->frequency==48000) valid=1; if((hdr->encoding != WAV_MP2 && hdr->encoding!=WAV_AC3 && hdr->encoding!=WAV_LPCM && hdr->encoding!=WAV_DTS)) { valid=0; } if(!valid) { deleteAudioFilter(audio); GUI_Error_HIG(("Incompatible audio"),QT_TR_NOOP( "For DVD, audio must be 48 kHz MP2(stereo), AC3, DTS or LPCM (stereo).")); return 0; } mux=MUXER_DVD; printf("PassThrough: Using DVD PS\n"); } } muxer=new mplexMuxer(); break; case ADM_TS: printf("Using TS output format\n"); muxer=new tsMuxer(); //lavMuxer(); mux=MUXER_TS; break; default: ADM_assert(0); break; } if(!muxer) { printf("No muxer ?\n"); return 0; } if(!muxer->open(name,0,mux,avifileinfo,audio->getInfo())) { delete muxer; muxer=NULL; printf("Muxer init failed\n"); return 0; } // In copy mode it is better to recompute the gop timestamp muxer->forceRestamp(); ///____________________________ work=new DIA_encoding(avifileinfo->fps1000); work->setCodec(QT_TR_NOOP("Copy")); work->setAudioCodec(QT_TR_NOOP("---")); work->setPhasis(QT_TR_NOOP("Saving")); if(!audioProcessMode()) work->setAudioCodec(QT_TR_NOOP("Copy")); else work->setAudioCodec(getStrFromAudioCodec(audio->getInfo()->encoding)); switch(mux) { case MUXER_TS: work->setContainer(QT_TR_NOOP("MPEG TS"));break; case MUXER_VCD: work->setContainer(QT_TR_NOOP("MPEG VCD"));break; case MUXER_SVCD: work->setContainer(QT_TR_NOOP("MPEG SVCD"));break; case MUXER_DVD: work->setContainer(QT_TR_NOOP("MPEG DVD"));break; default: ADM_assert(0); } uint32_t cur=0; uint32_t target_sample=0; double target_time; aviInfo info; video_body->getVideoInfo(&info); target_time=frameEnd-frameStart+1; target_time*=1000; target_time/=info.fps1000; // target_time in second target_time*=audio->getInfo()->frequency; target_sample=(uint32_t)floor(target_time); uint8_t *buffer = new uint8_t[avifileinfo->width * avifileinfo->height * 3]; uint8_t *audiobuffer = new uint8_t[4*48000*2]; // 2 sec worth of lpcm uint32_t position; EncoderCopy *copy=NULL; bitstream.data=buffer; bitstream.bufferSize=avifileinfo->width * avifileinfo->height * 3; /*************************** Special case : Multithreaded ***************************/ if(mux==MUXER_VCD || mux==MUXER_SVCD || mux==MUXER_DVD) { pthread_t audioThread,videoThread,muxerThread; copy=new EncoderCopy(NULL); muxerMT context; copy->configure(NULL); // memset(&context,0,sizeof(context)); context.videoEncoder=copy; context.audioEncoder=audio; context.muxer=( mplexMuxer *)muxer; context.nbVideoFrame=copy->getNbFrame(); context.audioTargetSample=target_sample; context.audioBuffer=audiobuffer; context.bitstream=&bitstream; context.opaque=(void *)work; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioSlave,&context)); ADM_assert(!pthread_create(&videoThread,NULL,(THRINP)copyVideoSlave,&context)); while(1) { accessMutex.lock(); if(context.audioDone==2 || context.videoDone==2 || !work->isAlive()) //ERROR { context.audioAbort=1; context.videoAbort=1; printf("[Copy] aborting\n"); } if(context.audioDone && context.videoDone) { printf("[Copy]Both audio & video done\n"); if(context.audioDone==1 && context.videoDone==1) ret=1; else ret=0; accessMutex.unlock(); goto _abt; } // Update UI work->setAudioSize(context.feedAudio); context.feedVideo=0; accessMutex.unlock(); ADM_usleep(1000*1000); } } /**************************************************************************************/ /* If we get here, it means output is MPEG_TS */ /* We must use the audio packet Queue */ /**************************************************************************************/ ADM_assert(mux==MUXER_TS); { PacketQueue *pq; uint32_t mx,sample; pthread_t audioThread; copy=new EncoderCopy(NULL); audioQueueMT context; uint8_t r; copy->configure(NULL); pq=new PacketQueue("TS audioQ",5000,2*1024*1024); memset(&context,0,sizeof(context)); context.audioEncoder=audio; context.audioTargetSample=target_sample; context.packetQueue=pq; // start audio thread ADM_assert(!pthread_create(&audioThread,NULL,(THRINP)defaultAudioQueueSlave,&context)); // Go! ADM_usleep(4000); mx=copy->getNbFrame(); printf("Writing %u frames\n",mx); for(int frame=0;frame<mx;frame++) { while(muxer->needAudio()) { if(pq->Pop(audiobuffer,&audiolen,&sample)) { if(audiolen) { muxer->writeAudioPacket(audiolen,audiobuffer); //work->feedAudioFrame(audiolen); } }else break; } ADM_assert(copy); bitstream.cleanup(frame); r=copy->encode ( frame, &bitstream); if(!r) { printf("TS:Frame %u error\n",frame); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); goto stopit; } muxer->writeVideoPacket( &bitstream); work->setFrame(frame,bitstream.len,bitstream.out_quantizer,mx); // work->feedFrame(bitstream.len); if(!work->isAlive()) { goto stopit; } } ret=1; stopit: 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; } // End ts case /************************************** TS End *********************************/ _abt: delete work; muxer->close(); delete muxer; delete [] buffer; delete [] audiobuffer; deleteAudioFilter(audio); if(copy) delete copy; return ret; }
//we receive all the packets here void packetReceiver::receive() { RakNet::Packet *packet; for (packet = this->nethandler->peer->Receive(); packet; this->nethandler->peer->DeallocatePacket(packet), packet = this->nethandler->peer->Receive()) { RakNet::BitStream bitstream(packet->data, packet->length, false); // The false is for efficiency so we don't make a copy of the passed data basePacket base; //we can receive bitstreams or something else if ((unsigned char)packet->data[0] == ID_TIMESTAMP) { bitstream.Read(base.useTimeStamp); bitstream.Read(base.timeStamp); bitstream.Read(base.typeId); } else { base.typeId = (unsigned char) packet->data[0]; } switch (base.typeId) //this is the packet's id (packetTypes.h) { //we receive the initial packet when connecting to a server case ID_CONNECTION_REQUEST_ACCEPTED: { FILE_LOG(logINFO) << "connection accepted"; this->nethandler->server = packet->systemAddress; } break; case INIT_CONNECTOR_PACKET: { RakNet::RakString receivedMap; bitstream.Read(receivedMap); const char* mapCStr = receivedMap.C_String(); std::stringstream s; s << mapCStr; unsigned long uniqueid; bitstream.Read(uniqueid); FILE_LOG(logINFO) << "received init connector: " << uniqueid; this->nethandler->client->uniqueid = uniqueid; this->nethandler->client->gameHandler.setMapFromStream(s); } break; case NEWPLAYER_PACKET: { unsigned long uniqueid; bitstream.Read(uniqueid); RakNet::RakString name; bitstream.Read(name); FILE_LOG(logINFO) << "NEW PLAYER RECEIVED " << uniqueid; World *world = &this->nethandler->client->gameHandler.currentWorld; world->addPlayer(uniqueid); } break; case PLAYERMOVE_PACKET: { //FILE_LOG(logDEBUG) << "RECEIVED PLAYER MOVE PACKET"; basePacket base; unsigned long uniqueid; bitstream.Read(uniqueid); float x; bitstream.Read(x); float y; bitstream.Read(y); float velx; bitstream.Read(velx); float vely; bitstream.Read(vely); int inputDirection; bitstream.Read(inputDirection); bool inputJump; bitstream.Read(inputJump); World *world = &this->nethandler->client->gameHandler.currentWorld; //world->playerMoveFromServer(uniqueid, x, y, velx, vely, inputDirection, inputJump); } break; } } }
/* * \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; }
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; }
uint8_t prepareDualPass(uint32_t bufferSize,uint8_t *buffer,char *TwoPassLogFile,DIA_encoding *encoding_gui,Encoder *_encode,uint32_t total) { uint32_t len, flag; FILE *tmp; uint8_t reuse=0,r; ADMBitstream bitstream(0); uint32_t prefill=0; uint32_t sent=0; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question(QT_TR_NOOP("\n Reuse the existing log-file ?"))) { reuse=1; } } if(!reuse) { encoding_gui->setPhasis ("1st Pass"); aprintf("**Pass 1:%lu\n",total); _encode->startPass1 (); bitstream.data=buffer; bitstream.bufferSize=bufferSize; preFilling2: bitstream.cleanup(0); if(!_encode->encode ( prefill, &bitstream))//&len, videoBuffer, &flags,&displayFrame)) { printf("MP4:First frame error\n"); GUI_Error_HIG (QT_TR_NOOP("Error while encoding"), NULL); return 0; } sent++; if(!bitstream.len) { prefill++; goto preFilling2; } printf("Pass 1 prefill : %u\n",prefill); for (uint32_t cf = 1; cf < total; cf++) { if (!encoding_gui->isAlive()) { abt: GUI_Error_HIG (QT_TR_NOOP("Aborting"), NULL); return 0; } bitstream.cleanup(cf); if(!prefill || cf+prefill<total) { r=_encode->encode ( prefill+cf, &bitstream); } else { r=_encode->encode ( total-1, &bitstream); } if (!r) { printf("\n Encoding of frame %lu failed !\n",cf); return 0; } sent++; encoding_gui->setFrame(cf,bitstream.len,bitstream.out_quantizer,total); } encoding_gui->reset(); aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } printf("First pass : send %u frames\n",sent); encoding_gui->setPhasis ("2nd Pass"); return 1; }
//________________________________________________ uint8_t ADM_ogmWriteProcess::initVideo(const char *name) { uint32_t w,h,fps1000,fcc; _prestore=0; _prestoring=1; _incoming = getLastVideoFilter (frameStart,frameEnd-frameStart); _togo=_incoming->getInfo()->nb_frames; _encode = getVideoEncoder (_incoming->getInfo()->width,_incoming->getInfo()->height); if (!_encode) return 0; TwoPassLogFile=new char[strlen(name)+6]; strcpy(TwoPassLogFile,name); strcat(TwoPassLogFile,".stat"); _encode->setLogFile(TwoPassLogFile,_togo); if (!_encode->configure (_incoming)) { delete _encode; _encode = NULL; GUI_Error_HIG (QT_TR_NOOP("Filter init failed"), NULL); return 0; }; w= _incoming->getInfo ()->width; h=_incoming->getInfo ()->height; fps1000=_incoming->getInfo ()->fps1000; _fps1000=fps1000; fcc= fourCC::get((uint8_t *)_encode->getCodecName()); _videoBuffer=new uint8_t[w*h*3]; encoding_gui->setCodec(_encode->getDisplayName()); //-----------------------VBR-------------------------------------- if (_encode->isDualPass ()) { uint8_t *buffer; uint32_t len, flag; FILE *tmp; uint8_t reuse=0; aprintf("\n** Dual pass encoding**\n"); if((tmp=fopen(TwoPassLogFile,"rt"))) { fclose(tmp); if(GUI_Question(QT_TR_NOOP("\n Reuse the existing log-file ?"))) { reuse=1; } } if(!reuse) { aprintf("**Pass 1:%lu\n",_togo); _encode->startPass1 (); encoding_gui->setCodec((char *)_encode->getCodecName()); encoding_gui->setPhasis("Pass one"); ADMBitstream bitstream(w*h*3); bitstream.data=_videoBuffer; //__________________________________ // now go to main loop..... //__________________________________ for (uint32_t cf = 0; cf < _togo; cf++) { bitstream.cleanup(cf); if (!_encode->encode (cf, &bitstream)) { printf("\n Encoding of frame %lu failed !\n",cf); return 0; } encoding_gui->setFrame(cf,bitstream.len,bitstream.out_quantizer,_togo); if(!encoding_gui->isAlive()) { return 0; } } aprintf("**Pass 1:done\n"); }// End of reuse if(!_encode->startPass2 ()) { printf("Pass2 ignition failed\n"); return 0; } encoding_gui->setPhasis("Pass 2"); } //-------------------------/VBR----------------------------------- else { encoding_gui->setPhasis("Encoding"); } // init save avi // now we build the new stream ! aprintf("**main pass:\n"); stream_header header; int64_t dur64; uint32_t dur32; uint16_t dur16; memset(&header,0,sizeof(header)); memcpy(&(header.streamtype),"video\0\0\0",8); MEMCPY(&(header.subtype),&fcc,4); //header.size=sizeof(header); dur32=sizeof(header); MEMCPY(&header.size,&dur32,4); MEMCPY(&(header.video.width),&w,4); MEMCPY(&(header.video.height),&h,4); // Timing .. double duration; // duration in 10us duration=fps1000; duration=1000./duration; duration*=1000*1000; duration*=10; dur64=(int64_t)duration; MEMCPY(&header.time_unit,&dur64,8); dur64=1; MEMCPY(&header.samples_per_unit,&dur64,8); dur32=0x10000; MEMCPY(&header.buffersize,&dur32,4); dur16=24; MEMCPY(&header.bits_per_sample,&dur16,2); //header.default_len=1; dur32=1; MEMCPY(&header.default_len,&dur32,4); return videoStream->writeHeaders(sizeof(header),(uint8_t *)&header); // +4 ? }
/* =================== idSWF::LoadSWF =================== */ bool idSWF::LoadSWF( const char* fullpath ) { idFile* rawfile = fileSystem->OpenFileRead( fullpath ); if( rawfile == NULL ) { idLib::Printf( "SWF File not found %s\n", fullpath ); return false; } swfHeader_t header; rawfile->Read( &header, sizeof( header ) ); if( header.W != 'W' || header.S != 'S' ) { idLib::Warning( "Wrong signature bytes" ); delete rawfile; return false; } if( header.version > 9 ) { idLib::Warning( "Unsupported version %d", header.version ); delete rawfile; return false; } bool compressed; if( header.compression == 'F' ) { compressed = false; } else if( header.compression == 'C' ) { compressed = true; } else { idLib::Warning( "Unsupported compression type %c", header.compression ); delete rawfile; return false; } idSwap::Little( header.fileLength ); // header.fileLength somewhat annoyingly includes the size of the header uint32 fileLength2 = header.fileLength - ( uint32 )sizeof( swfHeader_t ); // slurp the raw file into a giant array, which is somewhat atrocious when loading from the preload since it's already an idFile_Memory byte* fileData = ( byte* )Mem_Alloc( fileLength2, TAG_SWF ); size_t fileSize = rawfile->Read( fileData, fileLength2 ); delete rawfile; if( compressed ) { byte* uncompressed = ( byte* )Mem_Alloc( fileLength2, TAG_SWF ); if( !Inflate( fileData, ( int )fileSize, uncompressed, fileLength2 ) ) { idLib::Warning( "Inflate error" ); Mem_Free( uncompressed ); return false; } Mem_Free( fileData ); fileData = uncompressed; } idSWFBitStream bitstream( fileData, fileLength2, false ); swfRect_t frameSize; bitstream.ReadRect( frameSize ); if( !frameSize.tl.Compare( vec2_zero ) ) { idLib::Warning( "Invalid frameSize top left" ); Mem_Free( fileData ); return false; } frameWidth = frameSize.br.x; frameHeight = frameSize.br.y; frameRate = bitstream.ReadU16(); // parse everything mainsprite->Load( bitstream, true ); // now that all images have been loaded, write out the combined image idStr atlasFileName = "generated/"; atlasFileName += fullpath; atlasFileName.SetFileExtension( ".tga" ); WriteSwfImageAtlas( atlasFileName ); Mem_Free( fileData ); return true; }
bool FeatureDetector::match(Image image) { ImageBitstream bitstream(image); return match(bitstream); }