#include #include #include #include #include #include "VideoProcessor.h" #include "QVideoDevice.h" VideoProcessor::VideoProcessor() :_encoded_frame_size(256,256) { _decoded_output_device = NULL ; } bool VideoProcessor::processImage(const QImage& img,uint32_t size_hint,uint32_t& encoded_size) { VideoCodec *codec ; switch(_encoding_current_codec) { case VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO: codec = &_jpeg_video_codec ; break ; case VIDEO_PROCESSOR_CODEC_ID_DDWT_VIDEO: codec = &_ddwt_video_codec ; break ; default: codec = NULL ; } // std::cerr << "reducing to " << _frame_size.width() << " x " << _frame_size.height() << std::endl; void *data = NULL; encoded_size = 0 ; if(codec) { RsVOIPDataChunk chunk ; codec->encodeData(img.scaled(_encoded_frame_size,Qt::IgnoreAspectRatio,Qt::SmoothTransformation),size_hint,chunk) ; if(chunk.size == 0) // the codec might be buffering the frame for compression reasons return true ; _encoded_out_queue.push_back(chunk) ; return true ; } else return false ; } bool VideoProcessor::nextEncodedPacket(RsVOIPDataChunk& chunk) { if(_encoded_out_queue.empty()) return false ; chunk = _encoded_out_queue.front() ; _encoded_out_queue.pop_front() ; return true ; } void VideoProcessor::setInternalFrameSize(QSize s) { _encoded_frame_size = s ; } void VideoProcessor::receiveEncodedData(const RsVOIPDataChunk& chunk) { static const int HEADER_SIZE = 4 ; // read frame type. Use first 4 bytes to give info about content. // // Byte Meaning Values // 00 Codec CODEC_ID_JPEG_VIDEO Basic Jpeg codec // CODEC_ID_DDWT_VIDEO Differential wavelet compression // // 01 Unused Might be useful later // // 0203 Flags Codec specific flags. // if(chunk.size < HEADER_SIZE) { std::cerr << "JPEGVideoDecoder::decodeData(): Too small a data packet. size=" << chunk.size << std::endl; return ; } uint32_t codid = ((unsigned char *)chunk.data)[0] + (((unsigned char *)chunk.data)[1] << 8) ; uint16_t flags = ((unsigned char *)chunk.data)[2] + (((unsigned char *)chunk.data)[3] << 8) ; VideoCodec *codec ; switch(codid) { case VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO: codec = &_jpeg_video_codec ; break ; case VIDEO_PROCESSOR_CODEC_ID_DDWT_VIDEO: codec = &_ddwt_video_codec ; break ; default: codec = NULL ; } QImage img ; if(codec != NULL) codec->decodeData(chunk,img) ; if(_decoded_output_device) _decoded_output_device->showFrame(img) ; } void VideoProcessor::setMaximumFrameRate(uint32_t bytes_per_sec) { std::cerr << "Video Encoder: maximum frame rate is set to " << bytes_per_sec << " Bps" << std::endl; } ////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////////////////////////////////////////////// JPEGVideo::JPEGVideo() : _encoded_ref_frame_max_distance(50),_encoded_ref_frame_count(50) { } bool JPEGVideo::decodeData(const RsVOIPDataChunk& chunk,QImage& image) { // now see if the frame is a differential frame, or just a reference frame. uint16_t codec = ((unsigned char *)chunk.data)[0] + (((unsigned char *)chunk.data)[1] << 8) ; uint16_t flags = ((unsigned char *)chunk.data)[2] + (((unsigned char *)chunk.data)[3] << 8) ; assert(codec == VideoProcessor::VIDEO_PROCESSOR_CODEC_ID_JPEG_VIDEO) ; // un-compress image data QByteArray qb((char*)&((uint8_t*)chunk.data)[HEADER_SIZE],(int)chunk.size - HEADER_SIZE) ; if(!image.loadFromData(qb,"JPEG")) { std::cerr << "image.loadFromData(): returned an error.: " << std::endl; return false ; } if(flags & JPEG_VIDEO_FLAGS_DIFFERENTIAL_FRAME) { if(_decoded_reference_frame.size() != image.size()) { std::cerr << "Bad reference frame!" << std::endl; return false ; } QImage res = _decoded_reference_frame ; for(uint32_t i=0;i> 8) & 0xff ; ((unsigned char *)voip_chunk.data)[2] = flags & 0xff ; ((unsigned char *)voip_chunk.data)[3] = (flags >> 8) & 0xff ; memcpy(voip_chunk.data+HEADER_SIZE,qb.data(),qb.size()) ; voip_chunk.size = HEADER_SIZE + qb.size() ; voip_chunk.type = RsVOIPDataChunk::RS_VOIP_DATA_TYPE_VIDEO ; return true ; }