You are viewing a plain text version of this content. The canonical link for it is here.
Posted to bluesky-commits@incubator.apache.org by tp...@apache.org on 2008/06/04 02:48:20 UTC
svn commit: r662948 [25/31] - in /incubator/bluesky/NCstu-2.0: ./
autom4te.cache/ include/ intl/ po/ src/ src/.deps/ src/ffmpeg/ src/pic/
Added: incubator/bluesky/NCstu-2.0/src/en_de_video.cpp
URL: http://svn.apache.org/viewvc/incubator/bluesky/NCstu-2.0/src/en_de_video.cpp?rev=662948&view=auto
==============================================================================
--- incubator/bluesky/NCstu-2.0/src/en_de_video.cpp (added)
+++ incubator/bluesky/NCstu-2.0/src/en_de_video.cpp Tue Jun 3 19:48:16 2008
@@ -0,0 +1,5068 @@
+/*version
+*/
+static char *primary_version = "";
+static char *video_version_ = "1.2.0";
+
+
+#ifdef HAVE_1394_CONFIG_H
+#include "1394_config.h"
+#endif // HAVE_1394_CONFIG_H
+
+
+//V4l classes.
+#include <deque>
+#include <unistd.h>
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+/*
+using std::ostringstream;
+using std::setw;
+using std::setfill;
+*/
+#include <pthread.h>
+
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "en_de_video.h"
+
+extern int v4l_dev_num = 0;
+extern int delay_time = 0;
+
+extern "C"
+{
+//#include "support.h"
+#include <sys/types.h>
+#include <sys/soundcard.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+// pthread_t v4lthread;
+}
+
+static int ENCODE_YUV = 0;
+
+/** Send a request to the v4l device associated to a V4LStruct object.
+*/
+
+bool V4LDevice::request( int req, V4LStruct *v4l )
+{
+ ENCODE_YUV = getenv( "KINO_V4L_PATCHED" ) != NULL;
+ return request( req, v4l->getStruct() );
+}
+
+/** Send a request to the v4l device associated to an arbitrary address.
+*/
+
+bool V4LDevice::request( int req, void *addr )
+{
+ return ioctl( getHandle(), req, addr ) != -1;
+}
+
+V4LCapability::V4LCapability( V4LDevice *device )
+{
+ device->request( VIDIOCGCAP, this );
+}
+
+V4LCapability::~V4LCapability()
+{
+// cout << "Closing Capability" << endl;
+}
+
+void *V4LCapability::getStruct()
+{
+ return & capability;
+}
+
+char *V4LCapability::getName()
+{
+ return capability.name;
+}
+
+int V4LCapability::getNumberOfChannels()
+{
+ return capability.channels;
+}
+
+int V4LCapability::getNumberOfAudioDevices()
+{
+ return capability.audios;
+}
+
+int V4LCapability::getMinWidth()
+{
+ return capability.minwidth;
+}
+
+int V4LCapability::getMinHeight()
+{
+ return capability.minheight;
+}
+
+int V4LCapability::getMaxWidth()
+{
+ return capability.maxwidth;
+}
+
+int V4LCapability::getMaxHeight()
+{
+ return capability.maxheight;
+}
+
+bool V4LCapability::canCapture()
+{
+ return capability.type & VID_TYPE_CAPTURE;
+}
+
+bool V4LCapability::hasTuner()
+{
+ return capability.type & VID_TYPE_TUNER;
+}
+
+bool V4LCapability::hasChromakey()
+{
+ return capability.type & VID_TYPE_CHROMAKEY;
+}
+
+bool V4LCapability::hasClipping()
+{
+ return capability.type & VID_TYPE_CLIPPING;
+}
+
+bool V4LCapability::hasOverwrite()
+{
+ return capability.type & VID_TYPE_FRAMERAM;
+}
+
+bool V4LCapability::hasScaling()
+{
+ return capability.type & VID_TYPE_SCALES;
+}
+
+bool V4LCapability::isMonochrome()
+{
+ return capability.type & VID_TYPE_MONOCHROME;
+}
+
+bool V4LCapability::canSubCapture()
+{
+ return capability.type & VID_TYPE_SUBCAPTURE;
+}
+
+void V4LCapability::report()
+{
+
+/* cout << ">>> Name : " << this->getName() << endl;
+ cout << ">>> Channels : " << this->getNumberOfChannels() << endl;
+ cout << ">>> Audio : " << this->getNumberOfAudioDevices() << endl;
+ cout << ">>> Min Size : " << this->getMinWidth() << "," << this->getMinHeight() << endl;
+ cout << ">>> Max Size : " << this->getMaxWidth() << "," << this->getMaxHeight() << endl;
+ cout << ">>> Functions: " << endl;
+ if ( this->canCapture() )
+ cout << " + Can capture to memory" << endl;
+ if ( this->hasTuner() )
+ cout << " + Has a Tuner" << endl;
+ if ( this->hasChromakey() )
+ cout << " with Chromakey" << endl;
+ if ( this->hasClipping() )
+ cout << " with Clipping" << endl;
+ if ( this->hasOverwrite() )
+ cout << " overwrites buffer memory" << endl;
+ if ( this->hasScaling() )
+ cout << " + Has hardware support for image scaling" << endl;
+ if ( this->isMonochrome() )
+ cout << " - Monochrome only" << endl;
+ if ( this->canSubCapture() )
+ cout << " + Can capture part of the image" << endl;
+*/
+}
+
+V4LTuner::V4LTuner( V4LDevice *device, int index )
+{
+ this->device = device;
+ this->tuner.tuner = index;
+ this->device->request( VIDIOCGTUNER, this );
+}
+
+void *V4LTuner::getStruct()
+{
+ return & tuner;
+}
+
+void V4LTuner::report()
+{}
+
+int V4LTuner::getRangeLow()
+{
+ return tuner.rangelow;
+}
+
+void V4LTuner::setRangeLow( int low )
+{
+ tuner.rangelow = low;
+}
+
+int V4LTuner::getRangeHigh()
+{
+ return tuner.rangehigh;
+}
+
+void V4LTuner::setRangeHigh( int high )
+{
+ tuner.rangehigh = high;
+}
+
+int V4LTuner::getFlags()
+{
+ return tuner.flags;
+}
+
+void V4LTuner::setFlags( int flags )
+{
+ tuner.flags = flags;
+}
+
+int V4LTuner::getMode()
+{
+ return tuner.mode;
+}
+
+void V4LTuner::setMode( int mode )
+{
+ tuner.mode = mode;
+}
+
+int V4LTuner::getSignal()
+{
+ return tuner.signal;
+}
+
+V4LChannel::V4LChannel( V4LDevice *device, int index )
+{
+ memset( &channel, 0, sizeof( struct video_channel ) );
+ this->device = device;
+ this->channel.channel = index;
+ device->request( VIDIOCGCHAN, this );
+ device->request( VIDIOCSCHAN, this );
+ for ( unsigned int i = 0; i < getNumberOfTuners(); i ++ )
+ {
+ V4LTuner *tuner = new V4LTuner( this->device, i );
+ tuners.insert( tuners.end(), tuner );
+ }
+}
+
+V4LChannel::~V4LChannel()
+{
+// cout << "Channel destroyed" << endl;
+}
+
+void *V4LChannel::getStruct()
+{
+ return & channel;
+}
+
+char *V4LChannel::getName()
+{
+ return channel.name;
+}
+
+bool V4LChannel::setTuner( unsigned int index )
+{
+ if ( index >= 0 && index < tuners.size() )
+ {
+ current = tuners[ index ];
+ // FIXME: Hardcoded tuner settings
+ current->setRangeLow( 0 );
+ current->setRangeHigh( 0xffff );
+ return device->request( VIDIOCSTUNER, current );
+ }
+ else
+ {
+ return false;
+ }
+}
+
+unsigned int V4LChannel::getNumberOfTuners()
+{
+ return channel.tuners;
+}
+
+V4LTuner *V4LChannel::getTuner( unsigned int index )
+{
+ if ( index >= 0 && index < tuners.size() )
+ {
+ return tuners[ index ];
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+int V4LChannel::getSignal()
+{
+ device->request( VIDIOCGTUNER, current );
+ return current->getSignal();
+}
+
+void V4LChannel::report()
+{
+/*
+ cout << ">>>> Channel # " << channel.channel << endl;
+ cout << ">>>> Name : " << this->getName() << endl;
+ cout << ">>>> Tuners : " << this->getNumberOfTuners() << endl;
+ cout << ">>>> Flags : " << endl;
+ if ( channel.flags & VIDEO_VC_TUNER )
+ cout << " Channel has tuners" << endl;
+ if ( channel.flags & VIDEO_VC_AUDIO )
+ cout << " Channel has audio" << endl;
+ cout << ">>>> Type : " << endl;
+ if ( channel.type & VIDEO_TYPE_TV )
+ cout << " TV" << endl;
+ if ( channel.type & VIDEO_TYPE_CAMERA )
+ cout << " Camera" << endl;
+*/
+}
+
+/** Constructor for the V4L class.
+*/
+
+V4L::V4L()
+{
+// cout << "Opening V4L" << endl;
+}
+
+void V4L::setInfo( char *device, char *input, char *audio, int sample )
+{
+ this->device = device;
+ this->input = input;
+ this->audio = audio;
+ this->sample = sample;
+}
+
+bool V4L::openDevice()
+{
+ bool ret = true;
+
+ if ( !strcmp( this->input, "PAL" ) )
+ {
+// this->width = 720;
+// this->height = 576;
+ this->width = VideoWidth;
+ this->height = VideoHeight;
+ this->fps = 25;
+ this->frameSample = this->sample / this->fps;
+ }
+ else if ( !strcmp( this->input, "NTSC" ) )
+ {
+ this->width = 720;
+ this->height = 480;
+ this->fps = 30;
+ this->frameSample = this->sample / this->fps;
+ }
+
+ this->current = NULL;
+ this->fd = open( device, O_RDWR );
+ if(fd == -1){
+ perror( "Unable to open video device" );
+ return false;
+ }
+
+
+/*refer to old CVEncoder::InitCapture*/
+{
+ video_capability capability;
+ if (ioctl (fd, VIDIOCGCAP, &capability) != -1){
+ printf(" query was successful\n");
+ }
+ else{
+ perror("query");
+ }
+
+ if ((capability.type & VID_TYPE_CAPTURE) != 0){
+ printf("this device can capture video to memory\n");
+ }
+ else{
+ perror("can't capture video to memtory");
+ }
+
+ struct video_channel queryChannel;
+ int i = 0;
+ while (i < capability.channels)
+ {
+ queryChannel.channel = i;
+ if (ioctl (fd, VIDIOCGCHAN, &queryChannel) != -1)
+ { // ioctl success, queryChannel contains information about this channel
+ printf (" information about this channel:%d, %s\n", queryChannel.channel, queryChannel.name);
+ }
+ else
+ { // PErrorText("querychannel");
+ }
+ ++ i;
+ }
+
+ struct video_channel selectedChannel;
+ selectedChannel.channel = 0;
+ selectedChannel.norm = VIDEO_MODE_PAL;
+ if (ioctl (fd, VIDIOCSCHAN, &selectedChannel) == -1)
+ {
+ return false;
+ }
+
+
+ struct video_window captureWindow;
+ memset(&captureWindow, 0, sizeof(captureWindow));
+ captureWindow.width = VideoWidth;
+ captureWindow.height = VideoHeight;
+ if (ioctl (fd, VIDIOCSWIN, &captureWindow) == -1)
+ {
+// return false;
+ }
+
+ memset(&captureWindow, 0, sizeof(captureWindow));
+ if (ioctl (fd, VIDIOCGWIN, &captureWindow) == -1)
+ {
+ return false;
+ }
+
+ width = captureWindow.width;
+ height = captureWindow.height;
+ printf("width=%d,height=%d\n",width,height);
+
+}
+
+
+ int depth;
+ int palette;
+ struct video_picture imageProperties;
+
+ if (ioctl (fd, VIDIOCGPICT, &imageProperties) == -1)
+ { // failed to retrieve default image properties
+ return false;
+ }
+ depth = imageProperties.depth;
+ palette = imageProperties.palette;
+ printf("\nVideo:depth=%d,palette=%d\n",depth,palette);
+ if (ioctl (fd, VIDIOCSPICT, &imageProperties) == -1)
+ { // failed to retrieve default image properties
+ return false;
+ }
+
+/* refer to V4L::openDevice in kino program.*/
+/*
+ this->capability = new V4LCapability( this );
+ for ( int index = 0; index < capability->getNumberOfChannels(); index ++ )
+ {
+ V4LChannel *channel = new V4LChannel( this, index );
+ channels.insert( channels.end(), channel );
+ }
+ setCaptureResolution( this->width, this->height );
+
+*/
+
+
+ return ret;
+}
+
+/** Destructor for the V4L device.
+*/
+
+V4L::~V4L()
+{
+// cout << "Closing V4L" << endl;
+ if ( fd != -1 )
+ {
+ close( fd );
+ for ( unsigned int index = 0; index < channels.size(); index ++ )
+ delete channels[ index ];
+ delete this->capability;
+ }
+}
+
+/** Indicate if the device is available.
+
+ \return true if available, false otherwise
+*/
+
+bool V4L::deviceAvailable()
+{
+ return fd != -1;
+}
+
+/** Return the handle associated to the device.
+
+ \return the file descriptor of the open device.
+*/
+
+int V4L::getHandle()
+{
+ return fd;
+}
+
+/** Set specified channel.
+
+ \param channel channel to use
+ \return true if successful, false otherwise
+*/
+
+bool V4L::setChannel( unsigned int channel )
+{
+ if ( channel >= 0 && channel < channels.size() )
+ {
+ current = channels[ channel ];
+ return this->request( VIDIOCSCHAN, current );
+ }
+ else
+ {
+ return false;
+ }
+}
+
+/** Get the number of channels available.
+
+ \return the number of channels
+*/
+
+unsigned int V4L::getNumberOfChannels()
+{
+ return channels.size();
+}
+
+/** Get the specified channel.
+
+ \param channel channel to obtain
+ \return the number of channels
+*/
+
+V4LChannel *V4L::getChannel( unsigned int channel )
+{
+ if ( channel >= 0 && channel < channels.size() )
+ return channels[ channel ];
+ else
+ return NULL;
+}
+
+/** Set specified tuner.
+
+ \param tuner tuner to use
+ \return true if successful, false otherwise
+*/
+
+bool V4L::setTuner( unsigned int tuner )
+{
+ if ( current != NULL )
+ return current->setTuner( tuner );
+ else
+ return false;
+}
+
+/** Get the number of tuners associated to the current channel.
+
+ \return the number of tuners associated to the current channel
+*/
+
+unsigned int V4L::getNumberOfTuners( )
+{
+ if ( current != NULL )
+ return current->getNumberOfTuners();
+ else
+ return 0;
+}
+
+/** Get a tuner associated to the current channel.
+
+ \param tuner tuner object to obtain
+ \return a tuner object
+*/
+
+V4LTuner *V4L::getTuner( unsigned int tuner )
+{
+ if ( current != NULL )
+ return current->getTuner( tuner );
+ else
+ return NULL;
+}
+
+/** Set user defined resolution (where applicable).
+
+ \param width width of capture
+ \param height height of capture
+*/
+
+bool V4L::setCaptureResolution( int width, int height )
+{
+ if ( width > capability->getMaxWidth() ||
+ width < capability->getMinWidth() )
+ return false;
+ if ( height > capability->getMaxHeight() ||
+ height < capability->getMinHeight() )
+ return false;
+ if ( !capability->hasScaling() && (
+ width != capability->getMaxWidth() ||
+ height != capability->getMaxHeight() ) )
+ return false;
+ this->width = width;
+ this->height = height;
+// cout << "Capture resolution set to " << width << ", " << height << endl;
+ return true;
+}
+
+/** Get the capture width.
+
+ \return the width of the captured image
+*/
+
+int V4L::getWidth()
+{
+ return width;
+}
+
+/** Get the capture height.
+
+ \return the height of the captured image
+*/
+
+int V4L::getHeight()
+{
+ return height;
+}
+
+/** Turn on audio.
+*/
+
+void V4L::startAudio()
+{
+ struct video_audio audio;
+ ioctl( fd, VIDIOCGAUDIO, &audio );
+ if ( audio.flags & VIDEO_AUDIO_MUTE )
+ audio.flags ^= VIDEO_AUDIO_MUTE;
+// cout << "Volume : " << audio.volume << endl;
+ audio.volume = 65535;
+ ioctl( fd, VIDIOCSAUDIO, &audio );
+}
+
+/** Turn off audio.
+*/
+
+void V4L::stopAudio()
+{
+ struct video_audio audio;
+ ioctl( fd, VIDIOCGAUDIO, &audio );
+ audio.flags |= VIDEO_AUDIO_MUTE;
+// cout << "Volume : " << audio.volume << endl;
+ audio.volume = 0;
+ ioctl( fd, VIDIOCSAUDIO, &audio );
+}
+
+int V4L::mappedMemorySize( bool init )
+{
+ static video_mbuf buf;
+ if ( init == true )
+ {
+ init = 1;
+ ioctl( fd, VIDIOCGMBUF, &buf );
+// cout << ">>> Mapped Memory Size = " << buf.size << " frames are " << buf.frames << endl;
+ frame_maps = buf.frames;
+ }
+ return buf.size;
+}
+
+/** Initialise capture.
+
+ \param format v4l frame format (VIDEO_PALETTE_)
+ \return true if successful, false otherwise
+*/
+
+bool V4L::initialiseCapture( int format )
+{
+ size = width * height * 4;
+
+ map = mmap( 0, mappedMemorySize( true ), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0 );
+
+ if ( map != NULL )
+ {
+ for ( int i = 0; i < frame_maps; i ++ )
+ {
+ frame[ i ].frame = i;
+ frame[ i ].width = getWidth();
+ frame[ i ].height = getHeight();
+ frame[ i ].format = format;
+ }
+
+ struct timeval tv;
+ gettimeofday( &tv, NULL );
+ starttime = tv.tv_sec * 1000000 + tv.tv_usec;
+ frames = 0;
+ frame_next = 0;
+
+ int retry = 0;
+ while ( ioctl( fd, VIDIOCMCAPTURE, &frame[ 0 ] ) == -1 && retry ++ < frame_maps + 1 ) ;
+
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+/** Get the next frame.
+
+ \return the adress of the frame in the format specified
+*/
+
+void *V4L::getNextFrame()
+{
+ unsigned char * ret = NULL;
+
+ int current = frame_next;
+ frame_next = ( frame_next + 1 ) % frame_maps;
+
+ if ( ioctl( fd, VIDIOCMCAPTURE, &frame[ frame_next ] ) == -1 )
+ ; //cout << "Frame 1 Failed to initialise" << endl;
+ if ( ioctl( fd, VIDIOCSYNC, &frame[ current ].frame ) == -1 )
+ ; //cout << "Frame 0 Failed to sync" << endl;
+ ret = ( unsigned char * ) map + current * ( mappedMemorySize( ) / frame_maps );
+
+ frames ++;
+
+ return ( void * ) ret;
+}
+
+/** Turn off capture.
+*/
+
+void V4L::stopCapture()
+{
+ if ( map != NULL )
+ {
+ struct timeval tv;
+ gettimeofday( &tv, NULL );
+ long long endtime = tv.tv_sec * 1000000 + tv.tv_usec;
+ double fps = ( frames ) / ( ( ( double ) ( endtime - starttime ) ) / 1000000 );
+// cout << "fps: " << fps << endl;
+ munmap( map, mappedMemorySize() );
+ map = NULL;
+ int enable = 0;
+ ioctl( getHandle(), VIDIOCCAPTURE, &enable );
+ }
+}
+
+/** Get the current frequency of the tuner.
+
+ \return the current tuned in frequency.
+*/
+
+int V4L::getFrequency()
+{
+ unsigned long current;
+ ioctl( fd, VIDIOCGFREQ, ¤t );
+ return ( int ) current;
+}
+
+/** Set the current frequency of the tuner.
+
+ \param frequency frequency to set
+ \return the current tuned in frequency.
+*/
+
+bool V4L::setFrequency( int frequency )
+{
+ unsigned long val = ( unsigned long ) frequency & 0xffff;
+ return ioctl( fd, VIDIOCSFREQ, &val ) != -1;
+}
+
+/** Get the signal of the current tuned in frequency.
+*/
+
+int V4L::getSignal()
+{
+ return current->getSignal();
+}
+
+/** Gimme some info
+*/
+
+void V4L::report()
+{
+ capability->report();
+
+ for ( unsigned int index = 0; index < channels.size(); index ++ )
+ {
+ channels[ index ] ->report();
+ }
+}
+
+//V4l classes.
+
+
+
+
+
+extern void PErrorText(const char* error);
+
+int CVDecoder::input_pixfmt=PIX_FMT_RGBA32;
+
+
+#define STARTTIME { static int MaxTime=0; \
+ static int MinTime=1000; \
+ static int largecount=0; \
+ int IntervalTime=0; \
+ int64_t start_time=av_gettime();
+
+#define ENDTIME IntervalTime = av_gettime()-start_time; \
+ if(IntervalTime>40000) \
+ largecount++; \
+ if(MaxTime<IntervalTime) \
+ MaxTime=IntervalTime; \
+ if(MinTime>IntervalTime) \
+ MinTime=IntervalTime; \
+ printf("\nMaxTime=%d, MinTime=%d, largecount=%d, IntervalTime=%d\n", MaxTime, MinTime, largecount, IntervalTime);}
+
+CVEncoder::CVEncoder()
+{
+ m_pFrameBuf = 0;
+ m_pFrame = 0;
+ m_pCodec = 0;
+ m_pCodecCtx = 0;
+ m_memoryMap = (char*)-1;
+ m_pmemoryBuffer = 0;
+ m_mmaps = 0;
+ m_hDevice = -1;
+ m_bufferIndex = 0;
+ m_bInitCap = false;
+ m_bInit = false;
+}
+
+CVEncoder::~CVEncoder()
+{
+ CloseCap();
+
+ if(m_pFrameBuf){
+ free(m_pFrameBuf);
+ m_pFrameBuf = 0;
+ }
+
+
+ if(m_pFrame){
+ free(m_pFrame);
+ m_pFrame = 0;
+ }
+ if(m_pCodecCtx){
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+ m_bInitCap = false;
+ m_bInit = false;
+}
+
+bool CVEncoder::Init(enum CodecID nCodecID /*=CODEC_ID_MPEG1*/)
+{
+ m_bInit = false;
+ int width, height;
+
+ /*Init for encode*/
+ avcodec_init();
+ avcodec_register_all();
+
+ if(!InitCapture(width, height))
+ return false;
+// CloseCap();
+// if(!InitCapture(width, height))
+// return false;
+
+ m_width = width;
+ m_height = height;
+
+ //new a frame object.
+ if(m_pFrame){
+ free(m_pFrame);
+ m_pFrame = 0;
+ }
+ m_pFrame = avcodec_alloc_frame();
+
+ /* find the mpeg1 video encoder */
+ m_pCodec = avcodec_find_encoder(nCodecID);
+ if (!m_pCodec) {
+ PErrorText("codec not found");
+ return false;
+ }
+
+ if(m_pCodecCtx){
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+
+ m_pCodecCtx = avcodec_alloc_context();
+ /* resolution must be a multiple of two */
+ m_pCodecCtx->width = m_width;
+ m_pCodecCtx->height = m_height;
+ /* frames per second */
+ m_pCodecCtx->frame_rate = V_CODEC_framerate;
+ m_pCodecCtx->frame_rate_base= V_CODEC_frame_rate_base;
+ m_pCodecCtx->gop_size = V_CODEC_gop_size; /* emit one intra frame every ten frames */
+ m_pCodecCtx->bit_rate = 1128*1024; //1128kbps.
+
+ /* open it */
+ if (avcodec_open(m_pCodecCtx, m_pCodec) < 0) {
+ PErrorText("could not open codec");
+ return false;
+ }
+
+ // c->pix_fmt = PIX_FMT_YUV420P; // wy
+ // c->codec_type = CODEC_TYPE_VIDEO;
+
+ //malloc outbuf.
+ if(m_pFrameBuf){
+ free(m_pFrameBuf);
+ m_pFrameBuf = 0;
+ }
+
+ int image_size = avpicture_get_size (PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+
+ m_pFrameBuf = (uint8_t*)malloc(image_size);
+ if(m_pFrameBuf == 0){
+ PErrorText("FrameBuf malloc failed!");
+ return false;
+ }
+ /*Init for encode*/
+
+
+ avpicture_fill ((AVPicture*)m_pFrame, m_pFrameBuf, PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+ m_pFrame->type = FF_BUFFER_TYPE_SHARED;
+
+
+ m_bInit = true;
+ return true;
+}
+
+// for test encode.
+//void SaveVideoFile(char* buf, int bufsize)
+//{
+// fwrite(buf, bufsize, 1, pFile);
+// return;
+//}
+
+int CVEncoder::EncodeProcess(char *frameaddress, uint8_t *pOutBuf, int nOutsize)
+{
+ int iii;
+ if(!m_bInit)
+ return -2;
+
+ if(nOutsize<V_En_OutBufSize){
+ return -3;
+ }
+// STARTTIME
+ avpicture_fill(&m_pic_rgb, (uint8_t *)frameaddress, PIX_FMT_BGR24, m_pCodecCtx->width, m_pCodecCtx->height);
+ avpicture_fill((AVPicture*)m_pFrame, m_pFrameBuf, PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+ if (img_convert ((AVPicture*)m_pFrame, PIX_FMT_YUV420P,
+ &m_pic_rgb, PIX_FMT_BGR24, m_pCodecCtx->width, m_pCodecCtx->height) < 0) {
+ fprintf (stderr, "xtoffmpeg.XImageToFFMPEG(): pixel format conversion not handled ... aborting\n");
+ return -4;
+ }
+
+ m_VideoHeader.width=m_width;
+ m_VideoHeader.height=m_height;
+ memcpy((char *)pOutBuf,&m_VideoHeader, sizeof(VideoHeader));
+
+ iii = avcodec_encode_video(m_pCodecCtx, pOutBuf+sizeof(VideoHeader), nOutsize, m_pFrame);
+// printf("iii = %d, key_frame = %d, pict_type = %d\n",
+// iii, m_pFrame->key_frame, m_pFrame->pict_type);
+ // for test encode.
+ if(iii<=0)
+ return iii;
+// ENDTIME
+ return iii+sizeof(VideoHeader);
+}
+
+bool CVEncoder::InitCapture(int &width, int &height)
+{
+ CloseCap();
+ m_hDevice = open ("/dev/video0", O_RDWR);
+ if (m_hDevice != -1){
+ printf("\nopen successful\n");
+ }
+ else{
+ PErrorText("open video device: /dev/video0");
+ return false;
+ }
+
+ video_capability capability;
+ if (ioctl (m_hDevice, VIDIOCGCAP, &capability) != -1){
+ printf(" query was successful\n");
+ }
+ else{
+ perror("query");
+ }
+
+ if ((capability.type & VID_TYPE_CAPTURE) != 0){
+ printf("this device can capture video to memory\n");
+ }
+ else{
+ perror("can't capture video to memtory");
+ }
+
+ struct video_channel queryChannel;
+ int i = 0;
+ while (i < capability.channels)
+ {
+ queryChannel.channel = i;
+ if (ioctl (m_hDevice, VIDIOCGCHAN, &queryChannel) != -1)
+ { // ioctl success, queryChannel contains information about this channel
+ printf (" information about this channel:%d, %s\n", queryChannel.channel, queryChannel.name);
+ }
+ else
+ { PErrorText("querychannel");
+ }
+ ++ i;
+ }
+
+ struct video_channel selectedChannel;
+ selectedChannel.channel = 0;
+ selectedChannel.norm = VIDEO_MODE_PAL;
+ if (ioctl (m_hDevice, VIDIOCSCHAN, &selectedChannel) == -1)
+ {
+ PErrorText("could not set the selected channel");
+ return false;
+ }
+
+
+ struct video_window captureWindow;
+ memset(&captureWindow, 0, sizeof(captureWindow));
+ captureWindow.width = V_CODEC_width;
+ captureWindow.height = V_CODEC_height;
+ if (ioctl (m_hDevice, VIDIOCSWIN, &captureWindow) == -1)
+ {
+ PErrorText("Video Open Error: Could not set standar video size");
+// return false;
+ }
+
+ memset(&captureWindow, 0, sizeof(captureWindow));
+ if (ioctl (m_hDevice, VIDIOCGWIN, &captureWindow) == -1)
+ {
+ PErrorText("Video Open Error: Could not get video size");
+ return false;
+ }
+
+ width = captureWindow.width;
+ height = captureWindow.height;
+ printf("width=%d,height=%d\n",width,height);
+// if(width!=V_CODEC_width || height!=V_CODEC_height){
+// printf("\nVideo Open Error: Video size is not %d, %d\n", V_CODEC_width, V_CODEC_height);
+// return false;
+// }
+
+ int depth;
+ int palette;
+ struct video_picture imageProperties;
+
+ if (ioctl (m_hDevice, VIDIOCGPICT, &imageProperties) == -1)
+ { // failed to retrieve default image properties
+ return false;
+ }
+ depth = imageProperties.depth;
+ palette = imageProperties.palette;
+ printf("\nVideo:depth=%d,palette=%d\n",depth,palette);
+ if (ioctl (m_hDevice, VIDIOCSPICT, &imageProperties) == -1)
+ { // failed to retrieve default image properties
+ return false;
+ }
+
+// sleep(10);
+ m_pmemoryBuffer = new (struct video_mbuf);
+ if (ioctl (m_hDevice, VIDIOCGMBUF, m_pmemoryBuffer) == -1)
+ {
+ PErrorText("retrieve information about capture memory space");
+ return false;
+ }
+
+
+ // obtain memory mapped area
+
+ m_memoryMap = (char*)mmap (0, m_pmemoryBuffer->size, PROT_READ | PROT_WRITE, MAP_SHARED, m_hDevice, 0);
+ if ((int)m_memoryMap == -1)
+ {
+ PErrorText("retrieve pointer to memory mapped area");
+ return false;
+ }
+
+
+ // allocate structures
+
+ m_mmaps = (struct video_mmap*)(malloc (m_pmemoryBuffer->frames * sizeof (struct video_mmap)));
+ // fill out the fields
+ i = 0;
+ printf("\nmemoryBuffer.frames = %d\n", m_pmemoryBuffer->frames);
+ // sleep(100);
+ while (i < m_pmemoryBuffer->frames)
+ {
+ m_mmaps[i].frame = i;
+ m_mmaps[i].width = width;
+ m_mmaps[i].height = height;
+ m_mmaps[i].format = palette;
+ printf("frame%d=%d\n",i,m_mmaps[i].frame);
+ ++ i;
+ }
+
+
+ i = 0;
+ while (i < (m_pmemoryBuffer->frames-1))
+ {
+ if (ioctl (m_hDevice, VIDIOCMCAPTURE, &m_mmaps[i]) == -1)
+ {
+ PErrorText("capture request");
+ return false;
+
+ }
+ ++ i;
+ }
+
+ m_bufferIndex = m_pmemoryBuffer->frames-1;
+
+ m_bInitCap = true;
+ printf("\nVideo device open success!\n");
+ return true;
+}
+
+void CVEncoder::CloseCap()
+{
+
+ m_bInitCap = false;
+ m_bInit = false;
+
+ if(m_pmemoryBuffer){
+ if((int)m_memoryMap != -1){
+ // unmap the capture memory
+ munmap (m_memoryMap, m_pmemoryBuffer->size);
+ m_memoryMap = (char*)-1;
+ }
+ delete m_pmemoryBuffer;
+ m_pmemoryBuffer = 0;
+ }
+ if(m_mmaps){
+ free (m_mmaps);
+ m_mmaps = 0;
+ }
+
+ if(m_hDevice != -1){
+ close (m_hDevice);
+ m_hDevice = -1;
+ }
+
+// printf("\nVideo device closed.\n");
+}
+
+bool CVEncoder::GetCapSize(int &width, int &height)
+{
+ if(!m_bInit)
+ return false;
+
+ width = m_width;
+ height = m_height;
+
+ return true;
+}
+
+
+bool CVEncoder::Capture(char **frameaddress)
+{
+ if(!m_bInit)
+ return false;
+ STARTTIME
+ // send a request to begin capturing to the currently indexed buffer
+ if (ioctl (m_hDevice, VIDIOCMCAPTURE, &m_mmaps[m_bufferIndex]) == -1)
+ { perror("capture request failed");
+ }
+
+ // move bufferIndex to the next frame
+ ++ m_bufferIndex;
+ if (m_bufferIndex == m_pmemoryBuffer->frames)
+ { // bufferIndex is indexing beyond the last buffer
+ // set it to index the first buffer
+ m_bufferIndex = 0;
+ }
+
+ // wait for the currently indexed frame to complete capture
+ if (ioctl (m_hDevice, VIDIOCSYNC, &m_mmaps[m_bufferIndex]) == -1)
+ { perror(" sync request failed");
+ }
+
+ *frameaddress=m_memoryMap + m_pmemoryBuffer->offsets[m_bufferIndex];
+ ENDTIME
+ return true;
+}
+
+void CVEncoder::GetColorInfo (XImage *image, ColorInfo *ci /* return struct */)
+{
+ unsigned long red_mask, green_mask, blue_mask, alpha_mask;
+ // the shifts are unsigned longs as well
+
+ if (!ci)
+ return;
+
+ // setting shifts and bit_depths to zero
+ ci->red_shift = ci->green_shift = ci->blue_shift = ci->alpha_shift = 0;
+ ci->red_bit_depth = ci->green_bit_depth = ci->blue_bit_depth =
+ ci->alpha_bit_depth = 0;
+
+ red_mask = image->red_mask;
+ if (red_mask > 0) {
+ // shift red_mask to the right till all empty bits have been
+ // shifted out and count how many they were
+ while ((red_mask & 0x01) == 0) {
+ red_mask >>= 1;
+ ci->red_shift++;
+ }
+ // count how many bits are set in the mask = depth
+ while ((red_mask & 0x01) == 1) {
+ red_mask >>= 1;
+ ci->red_bit_depth++;
+ }
+ }
+
+ ci->red_max_val = (1 << ci->red_bit_depth) - 1;
+
+ green_mask = image->green_mask;
+ if (green_mask > 0) {
+ while ((green_mask & 0x01) == 0) {
+ green_mask >>= 1;
+ ci->green_shift++;
+ }
+ while ((green_mask & 0x01) == 1) {
+ green_mask >>= 1;
+ ci->green_bit_depth++;
+ }
+ }
+ ci->green_max_val = (1 << ci->green_bit_depth) - 1;
+
+ blue_mask = image->blue_mask;
+ if (blue_mask > 0) {
+ while ((blue_mask & 0x01) == 0) {
+ blue_mask >>= 1;
+ ci->blue_shift++;
+ }
+ while ((blue_mask & 0x01) == 1) {
+ blue_mask >>= 1;
+ ci->blue_bit_depth++;
+ }
+ }
+ ci->blue_max_val = (1 << ci->blue_bit_depth) - 1;
+
+ /* over all max values */
+ // whatever they are good for
+ ci->max_val = max (ci->red_max_val, ci->green_max_val);
+ ci->max_val = max (ci->blue_max_val, ci->max_val);
+ ci->bit_depth = max (ci->red_bit_depth, ci->green_bit_depth);
+ ci->bit_depth = max (ci->blue_bit_depth, ci->bit_depth);
+ if (image->bits_per_pixel > image->depth) {
+ /* alpha? */
+ // this seems to not reflect X's ignorance of alpha in its
+ // masks
+ ci->alpha_mask = ~
+ (image->red_mask | image->blue_mask | image->green_mask);
+ alpha_mask = ci->alpha_mask;
+ if (alpha_mask > 0) {
+ while ((alpha_mask & 0x01) == 0) {
+ alpha_mask >>= 1;
+ ci->alpha_shift++;
+ }
+ while ((alpha_mask & 0x01) == 1) {
+ alpha_mask >>= 1;
+ ci->alpha_bit_depth++;
+ }
+ }
+ ci->alpha_max_val = (1 << ci->alpha_bit_depth) - 1;
+ }
+}
+
+
+//CVDecoder class.
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+CVDecoder::CVDecoder()
+{
+ m_pCodec = 0;
+ m_pCodecCtx = 0;
+ m_pOutFrame = 0;
+ m_bInit = false;
+
+ m_display = 0;
+ m_win = 0;
+ m_image = 0;
+
+}
+
+CVDecoder::~CVDecoder()
+{
+ m_bInit = false;
+
+ if(m_pOutFrame){
+ free(m_pOutFrame);
+ m_pOutFrame = 0;
+ }
+ if(m_pCodecCtx){
+ if(m_pCodecCtx->extradata){
+ free(m_pCodecCtx->extradata);
+ m_pCodecCtx->extradata = 0;
+ m_pCodecCtx->extradata_size = 0;
+ }
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+
+ if(m_image){
+ XDestroyImage(m_image);
+ //m_image->f.destroy_image(m_image);
+ m_image = 0;
+ }
+
+
+ if(m_display){
+ if(m_win){
+ XClearWindow(m_display, m_win);
+ m_win = 0;
+ }
+ if(m_d){
+ XClearWindow(m_display, m_d);
+ m_d = 0;
+ }
+
+ XCloseDisplay(m_display);
+ m_display = 0;
+ }
+
+}
+
+bool CVDecoder::CreateXImage(Drawable parent, int x, int y, int width, int height)
+{
+ int screen_num;
+
+ GdkPixbuf *original_pixbuf;
+
+ gint original_width, original_height;
+ GdkColorspace original_color;
+ gboolean original_alpha;
+ gboolean pixbuf_has_alpha;
+ XSetWindowAttributes win_attr;
+ XImage *p_image = NULL;
+ if(!m_bInit)
+ return false;
+
+
+ CloseXImage();
+
+ m_imagemutex.Lock();
+
+ m_display = XOpenDisplay(NULL);
+ screen_num = DefaultScreen(m_display);
+ m_gc = DefaultGC(m_display, screen_num);
+ m_d = RootWindow(m_display,screen_num);
+
+ m_win = XCreateWindow(m_display, parent,
+ x, y, width, height, 1, XDefaultDepth(m_display, screen_num),
+ InputOutput, CopyFromParent, 0, &win_attr);
+
+ if(gdk_pixbuf_new_from_file ("pic/teacher2.bmp", NULL)==NULL)
+ {
+ XSetWindowBackgroundPixmap(m_display,m_win,ParentRelative);
+ XMapWindow(m_display, m_win);
+ }
+
+ else
+ {
+ original_pixbuf = gdk_pixbuf_new_from_file ("pic/teacher2.bmp", NULL);
+ pixbuf_has_alpha = gdk_pixbuf_get_has_alpha (original_pixbuf);
+ original_color = gdk_pixbuf_get_colorspace(original_pixbuf);
+ original_alpha = gdk_pixbuf_get_has_alpha(original_pixbuf);
+ original_width = gdk_pixbuf_get_width (original_pixbuf);
+ original_height = gdk_pixbuf_get_height (original_pixbuf);
+ printf("original_alpha = %d\n", original_alpha);
+ printf("original_color = %d\n", original_color);
+ printf("original_width = %d\n", original_width);
+ printf("original_height = %d\n", original_height);
+ printf("n_channles = %d\n", gdk_pixbuf_get_n_channels(original_pixbuf));
+
+
+
+
+ Pixmap pixmap=XCreatePixmap(m_display,m_win, original_width, original_height, XDefaultDepth(m_display,screen_num));
+ XSetWindowBackgroundPixmap(m_display, m_win, pixmap);
+
+ p_image = XGetImage(m_display, //è·åå½åå±å¹ææ¾ç¤ºå¾å
+ m_d,
+ 0, 0,
+ original_width,
+ original_height,
+ AllPlanes, ZPixmap);
+ if(!p_image){
+ printf("error\n");
+ exit(10);
+ }
+
+
+ AVPicture pic_rgb24, pic_rgb32;
+ if(m_display && p_image && pixmap){
+ avpicture_fill(&pic_rgb32, (uint8_t*)p_image->data, PIX_FMT_RGBA32,
+ original_width, original_height);
+ avpicture_fill(&pic_rgb24, gdk_pixbuf_get_pixels(original_pixbuf), PIX_FMT_RGB24,
+ original_width, original_height);
+
+ if(img_convert(&pic_rgb32, PIX_FMT_RGBA32, &pic_rgb24, PIX_FMT_RGB24,
+ original_width, original_height) < 0){
+ printf("Error pixel format conversion");
+ return -1;
+ }
+
+ XPutImage(m_display, pixmap, m_gc, p_image,
+ 0,0, 0, 0,
+ original_width, original_height);
+
+
+ }
+
+ XMapWindow(m_display, m_win);
+ XFreePixmap(m_display,pixmap);
+ gdk_pixbuf_unref(original_pixbuf);
+ XDestroyImage(p_image);
+ }
+
+ // Init GlobalVar.image
+ //
+ //m_d = RootWindow(m_display,screen_num);
+
+ m_image = XGetImage(m_display, //ÃÅ¡ÃÂ÷ÃÂ¥ÃÂÃÂÃÂ¥Ã
ÂÃÂÃÂ¥ÃÂÃÂÃ¥ñÃÂÃ¥ùÃÂÃÅ ÃÂÃÂÃÅ ÃÂÃ
žÃ§â¬úÃÂ¥ÃÂÃ
žÃÂ¥ÃÂÃÂ1â¬7
+ m_d,
+ 0, 0,
+ m_width, m_height,
+ AllPlanes, ZPixmap);
+
+/*
+ static Visual * visual = 0;
+ if(visual == 0){
+ visual = DefaultVisual(m_display, screen_num);
+ }
+ m_image = XCreateImage(m_display, visual, depth, ZPixmap, 0, data, width, height, bitmap_pad,
+ bytes_per_line)
+*/
+ if(!m_image){
+ printf("XGetImage error\n");
+ m_imagemutex.Unlock();
+ return false;
+ }
+
+ m_imagemutex.Unlock();
+ return true;
+}
+
+void CVDecoder::CloseXImage()
+{
+ if(!m_bInit)
+ return ;
+
+ m_imagemutex.Lock();
+
+ if(m_image){
+ XDestroyImage(m_image);
+// m_image->f.destroy_image(m_image);
+ m_image = 0;
+ }
+
+ if(m_display){
+ if(m_win){
+ XUnmapWindow(m_display, m_win);
+ XClearWindow(m_display, m_win);
+ m_win = 0;
+ }
+
+ if(m_d){
+ XClearWindow(m_display, m_d);
+ m_d = 0;
+ }
+
+ XCloseDisplay(m_display);
+ m_display = 0;
+ }
+
+ m_imagemutex.Unlock();
+ return ;
+}
+
+
+bool CVDecoder::Init(int width, int height, enum CodecID nCodecID)
+{
+ if(m_bInit)
+ return true;
+
+ avcodec_init();
+ avcodec_register_all();
+
+
+ if(!m_imagemutex.IsInitialized()){
+ if(m_imagemutex.Init() < 0)
+ return false;
+ }
+
+ m_width = width;
+ m_height = height;
+
+
+ // find the video decoder
+ m_pCodec = avcodec_find_decoder(nCodecID);
+ if (!m_pCodec) {
+ PErrorText("Codec not found\n");
+ return false;
+ }
+
+ if(m_pOutFrame){
+ free(m_pOutFrame);
+ m_pOutFrame = 0;
+ }
+ m_pOutFrame = avcodec_alloc_frame();
+
+ if(m_pCodecCtx){
+ if(m_pCodecCtx->extradata){
+ free(m_pCodecCtx->extradata);
+ m_pCodecCtx->extradata = 0;
+ m_pCodecCtx->extradata_size = 0;
+ }
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+ m_pCodecCtx = avcodec_alloc_context();
+ m_pCodecCtx->extradata = 0;
+ m_pCodecCtx->extradata_size = 0;
+
+ // put sample parameters
+ m_pCodecCtx->bit_rate = 512*1024;
+ // resolution must be a multiple of two
+ m_pCodecCtx->width = m_width;
+ m_pCodecCtx->height = m_height;
+ // frames per second
+ m_pCodecCtx->frame_rate = CVEncoder::V_CODEC_framerate;
+ m_pCodecCtx->frame_rate_base= CVEncoder::V_CODEC_frame_rate_base;
+ // emit one intra frame every ten frames
+ m_pCodecCtx->gop_size = CVEncoder::V_CODEC_gop_size;
+
+ m_pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ m_pCodecCtx->extradata = malloc(V_De_ExtraHeaderSize);
+ if(m_pCodecCtx->extradata == 0){
+ return false;
+ }
+ m_pCodecCtx->extradata_size = V_De_ExtraHeaderSize;
+
+ // pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
+ // pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
+
+ // we dont send complete frames
+ if(m_pCodec->capabilities&CODEC_CAP_TRUNCATED)
+ m_pCodecCtx->flags|= CODEC_FLAG_TRUNCATED;
+
+ // open it
+ if (avcodec_open(m_pCodecCtx, m_pCodec) < 0) {
+ PErrorText("could not open codec");
+ return false;
+ }
+
+ m_bInit = true;
+ return true;
+}
+
+
+int CVDecoder::DecodeProcess(uint8_t *encodeddata_v, const int encodeddatasize_v)
+{
+ bool isPaintPic;
+ int realsize, i;
+ int got_picture ;
+
+ if(!m_bInit){
+ return -1;
+ }
+
+ int left = 0;
+ int len;
+
+ m_imagemutex.Lock();
+
+ for(i = 0 ; ; i++){
+ if(encodeddatasize_v - i * V_De_INBUF_SIZE >= V_De_INBUF_SIZE)
+ realsize = V_De_INBUF_SIZE;
+ else
+ realsize = encodeddatasize_v - i * V_De_INBUF_SIZE;
+
+ if(realsize <= 0)
+ break;
+
+ left = 0;
+ isPaintPic = false;
+ while(realsize > 0){
+
+ m_pCodecCtx->width = m_width;
+ m_pCodecCtx->height = m_height;
+
+ len = avcodec_decode_video(m_pCodecCtx, m_pOutFrame, &got_picture,
+ (encodeddata_v + i * V_De_INBUF_SIZE + left), realsize);
+ // printf("len = %d, got_picture = %d, linesize=%d\n", len, got_picture, m_pOutFrame->linesize[0]);
+
+ if(len < 0){
+ PErrorText("Error while decoding");
+ m_imagemutex.Unlock();
+ return -2;
+ }
+
+ if(m_image != 0){
+
+ m_encoder.GetColorInfo (m_image, &c_info);
+ switch (m_image->bits_per_pixel) {
+ case 8:
+ input_pixfmt = PIX_FMT_PAL8;
+ break;
+ case 16:
+ if ( m_image->red_mask == 0xF800 && m_image->green_mask == 0x07E0
+ && m_image->blue_mask == 0x1F ) {
+ input_pixfmt = PIX_FMT_RGB565;
+ } else if ( m_image->red_mask == 0x7C00 && m_image->green_mask == 0x03E0
+ && m_image->blue_mask == 0x1F ) {
+ input_pixfmt = PIX_FMT_RGB555;
+ } else {
+ fprintf (stderr, "xtoffmpeg.XImageToFFMPEG(): rgb ordering at image depth %i not supported ... aborting\n", m_image->bits_per_pixel);
+ fprintf (stderr, "xtoffmpeg.XImageToFFMPEG(): color masks: r 0x%.6lX g 0x%.6lX b 0x%.6lX\n", m_image->red_mask, m_image->green_mask, m_image->blue_mask);
+ }
+ break;
+ case 24:
+ if ( m_image->red_mask == 0xFF0000 && m_image->green_mask == 0xFF00
+ && m_image->blue_mask == 0xFF ) {
+ input_pixfmt = PIX_FMT_BGR24;
+ } else if ( m_image->red_mask == 0xFF && m_image->green_mask == 0xFF00
+ && m_image->blue_mask == 0xFF0000 ) {
+ input_pixfmt = PIX_FMT_RGB24;
+ } else {
+ PErrorText("xtoffmpeg.XImageToFFMPEG(): rgb ordering at image depth not supported ... aborting\n");
+ PErrorText("xtoffmpeg.XImageToFFMPEG(): color masks");
+ return false;
+ }
+ break;
+ case 32:
+ if ( c_info.alpha_mask == 0xFF000000 && m_image->green_mask == 0xFF00 ) {
+ // byte order is relevant here, not endianness
+ // endianness is handled by avcodec, but atm no such thing
+ // as having ABGR, instead of ARGB in a word. Since we
+ // need this for Solaris/SPARC, but need to do the conversion
+ // for every frame we do it outside of this loop, cf. below
+ // this matches both ARGB32 and ABGR32
+ input_pixfmt = PIX_FMT_RGBA32;
+ } else {
+ PErrorText("xtoffmpeg.XImageToFFMPEG(): image depth not supported ... aborting");
+ return false;
+ }
+ break;
+ default:
+ PErrorText("xtoffmpeg.XImageToFFMPEG(): image depth not supported ... aborting");
+ return false;
+ }
+ }
+
+ if(got_picture){
+ if(!isPaintPic){
+ if(m_display && m_image && m_win){
+
+ avpicture_fill(&pic_rgb, (uint8_t*)m_image->data, input_pixfmt,
+ m_width, m_height);
+
+ if(img_convert(&pic_rgb, input_pixfmt, (AVPicture*)m_pOutFrame, PIX_FMT_YUV420P,
+ m_width, m_height) < 0){
+ PErrorText("Error pixel format conversion");
+ m_imagemutex.Unlock();
+ return -3;
+ }
+
+ XPutImage(m_display, m_win, m_gc, m_image,
+ 0, 0, 0, 0,
+ m_width, m_height);
+
+ }
+ }
+ isPaintPic = true;
+
+ }
+ realsize -= len;
+ left += len;
+ }
+ }
+
+ m_imagemutex.Unlock();
+ return 0;
+}
+
+void CVDecoder::CloseCodec()
+{
+ m_bInit = false;
+
+ if(m_pOutFrame){
+ free(m_pOutFrame);
+ m_pOutFrame = 0;
+ }
+ if(m_pCodecCtx){
+ if(m_pCodecCtx->extradata){
+ free(m_pCodecCtx->extradata);
+ m_pCodecCtx->extradata = 0;
+ m_pCodecCtx->extradata_size = 0;
+ }
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+
+}
+
+bool CVDecoder::ResetCodec(const int width, const int height)
+{
+ CodecID nCodecID = m_pCodecCtx->codec_id;
+ CloseCodec();
+ m_bInit = false;
+
+ m_width = width;
+ m_height = height;
+
+ // find the video decoder
+ m_pCodec = avcodec_find_decoder(nCodecID);
+ if (!m_pCodec) {
+ PErrorText("Codec not found");
+ return false;
+ }
+
+ if(m_pOutFrame){
+ free(m_pOutFrame);
+ m_pOutFrame = 0;
+ }
+ m_pOutFrame = avcodec_alloc_frame();
+
+ if(m_pCodecCtx){
+ if(m_pCodecCtx->extradata){
+ free(m_pCodecCtx->extradata);
+ m_pCodecCtx->extradata = 0;
+ m_pCodecCtx->extradata_size = 0;
+ }
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+ m_pCodecCtx = avcodec_alloc_context();
+ m_pCodecCtx->extradata = 0;
+ m_pCodecCtx->extradata_size = 0;
+
+ // put sample parameters
+ m_pCodecCtx->bit_rate = 512*1024;
+ // resolution must be a multiple of two
+ m_pCodecCtx->width = m_width;
+ m_pCodecCtx->height = m_height;
+ // frames per second
+ m_pCodecCtx->frame_rate = CVEncoder::V_CODEC_framerate;
+ m_pCodecCtx->frame_rate_base= CVEncoder::V_CODEC_frame_rate_base;
+ // emit one intra frame every ten frames
+ m_pCodecCtx->gop_size = CVEncoder::V_CODEC_gop_size;
+
+ m_pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
+ m_pCodecCtx->extradata = malloc(V_De_ExtraHeaderSize);
+ if(m_pCodecCtx->extradata == 0){
+ return false;
+ }
+ m_pCodecCtx->extradata_size = V_De_ExtraHeaderSize;
+
+ // pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
+ // pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
+
+ // we dont send complete frames
+ if(m_pCodec->capabilities&CODEC_CAP_TRUNCATED)
+ m_pCodecCtx->flags|= CODEC_FLAG_TRUNCATED;
+
+ // open it
+ if (avcodec_open(m_pCodecCtx, m_pCodec) < 0) {
+ PErrorText("could not open codec");
+ return false;
+ }
+
+ m_bInit = true;
+ return true;
+
+}
+
+//CVideoSender class.
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+CVideoSender::CVideoSender() : m_sendthread(SendBufSize)
+{
+ stop = false;
+ m_bIsRecord = false;
+ m_bInit = 0;
+
+ m_hFile = 0;
+ m_mode = ModeNone;
+// m_playback = 0;
+
+ if(!m_initmutex.IsInitialized()){
+ m_initmutex.Init();
+ }
+
+}
+
+CVideoSender::~CVideoSender()
+{
+ //first stop thread, because m_pOutBuf is being used by Thread();
+ Stop();
+
+ //close file.
+ if(m_hFile){
+ fclose(m_hFile);
+ m_hFile = 0;
+ }
+
+ //free buffer.
+ if(m_pOutBuf!=0)
+ free(m_pOutBuf);
+}
+
+#define MAX_PACKET_SIZE 10*1024
+bool CVideoSender::Init(int nHostPort)
+{
+ if(IsInitialized())
+ return true;
+
+ if(!m_imagemutex.IsInitialized()){
+ if(m_imagemutex.Init() < 0)
+ return false;
+ }
+
+ if(!m_sendthread.Init(nHostPort))
+ return false;
+
+ if(m_pOutBuf==0){
+ m_pOutBuf = (uint8_t*)malloc(CVEncoder::V_En_OutBufSize);
+ if(m_pOutBuf==0){
+ return false;
+ }
+
+ }
+
+ //Init sencoder.
+ if(!m_vencoder.Init(CODEC_ID_MPEG1VIDEO)){
+ return false;
+ }
+
+ if (!m_modemutex.IsInitialized())
+ {
+ if (m_modemutex.Init() < 0)
+ return -2;
+ }
+
+
+ m_bIsRecord = false;
+ m_bInit = true;
+ return m_bInit;
+}
+
+bool CVideoSender::IsInitialized()
+{
+ bool b;
+
+ m_initmutex.Lock();
+ b = m_bInit;
+ m_initmutex.Unlock();
+
+ return b;
+}
+
+bool CVideoSender::CreateXImage(Drawable parent, int x, int y, int width, int height)
+{
+ int screen_num;
+
+ if(!IsInitialized())
+ return false;
+
+
+ CloseXImage();
+
+ m_imagemutex.Lock();
+
+ m_display = XOpenDisplay(NULL);
+ screen_num = DefaultScreen(m_display);
+
+ m_win = XCreateSimpleWindow(m_display, //display
+ parent, //çÃÂöçêÃÂÃÂ¥ÃÂã
+ x, y, width, height, //Ãâ¬Ã
ÂÃÂçÃ
ÂîÃÂ¥ÃÂÃÂÃ¥âÃ¥ðÃÂ1â¬7
+ 0, //ÃÅ¡Ã
žÃ¹Ã§ÃÂÃÂÃ¥îÃ
ÂÃ¥úÃ
Â
+ BlackPixel(m_display, screen_num), //ÃÂ¥ÃÂÃÂÃÅ ÃÂïÃÅ¡ÃÂò
+ 65535/20);//ÃÅ¡ÃÂÃÂÃÅ ÃÂïÃÅ¡ÃÂò
+
+ XMapWindow(m_display, m_win);
+ m_gc = DefaultGC(m_display, screen_num);
+
+ // Init GlobalVar.image
+ //
+ int imagewidth, imageheight;
+ m_vencoder.GetCapSize(imagewidth, imageheight);
+
+ m_image = XGetImage(m_display, //ÃÅ¡ÃÂ÷ÃÂ¥ÃÂÃÂÃÂ¥Ã
ÂÃÂÃÂ¥ÃÂÃÂÃ¥ñÃÂÃ¥ùÃÂÃÅ ÃÂÃÂÃÅ ÃÂÃ
žÃ§â¬úÃÂ¥ÃÂÃ
žÃÂ¥ÃÂÃÂ1â¬7
+ m_win,
+ 0, 0,
+ imagewidth, imageheight,
+ AllPlanes, ZPixmap);
+ if(!m_image){
+ PErrorText("XGetImage error\n");
+ m_imagemutex.Unlock();
+ return false;
+ }
+
+ m_imagemutex.Unlock();
+ return true;
+}
+
+void CVideoSender::CloseXImage()
+{
+ if(!IsInitialized())
+ return ;
+
+ m_imagemutex.Lock();
+
+ if(m_image){
+ XDestroyImage(m_image);
+// m_image->f.destroy_image(m_image);
+ m_image = 0;
+ }
+
+ if(m_display){
+ if(m_win){
+ XUnmapWindow(m_display, m_win);
+ XClearWindow(m_display, m_win);
+ m_win = 0;
+ }
+ XCloseDisplay(m_display);
+ m_display = 0;
+ }
+
+ m_imagemutex.Unlock();
+}
+
+void CVideoSender::Playback(uint8_t* videodata, int width, int height)
+{
+ AVPicture pic_rgb24, pic_rgb32;
+
+ if(!IsInitialized())
+ return;
+
+ m_imagemutex.Lock();
+
+// printf("****************%d\n",CVDecoder::input_pixfmt);
+ if(m_display && m_image && m_win){
+
+ avpicture_fill(&pic_rgb32, (uint8_t*)m_image->data, CVDecoder::input_pixfmt,
+ width, height);
+ avpicture_fill(&pic_rgb24, videodata, PIX_FMT_BGR24,
+ width, height);
+
+ if(img_convert(&pic_rgb32, CVDecoder::input_pixfmt, &pic_rgb24, PIX_FMT_BGR24,
+ width, height) < 0){
+ PErrorText("Error pixel format conversion");
+ m_imagemutex.Unlock();
+ return ;
+ }
+
+
+ XPutImage(m_display, m_win, m_gc, m_image,
+ 0, 0, 0, 0,
+ width, height);
+ }
+
+ m_imagemutex.Unlock();
+ return;
+}
+
+
+int CVideoSender::Start(char* szFile /* =0 */, bool bIsRecord /* =false */)
+{
+ if(!IsInitialized())
+ return -1;
+
+ if (JThread::IsRunning())
+ return 0;
+
+ if (!stopmutex.IsInitialized())
+ {
+ if (stopmutex.Init() < 0)
+ return -2;
+ }
+
+ stop = false;
+
+ if (!m_recordmutex.IsInitialized())
+ {
+ if (m_recordmutex.Init() < 0)
+ return -2;
+ }
+
+ m_bIsRecord = bIsRecord;
+
+ if(bIsRecord && szFile != 0){
+ if(m_hFile){
+ fclose(m_hFile);
+ m_hFile = 0;
+ }
+
+ m_hFile = fopen(szFile, "wb");
+ if(m_hFile==0){
+ return -3;
+ }
+
+ m_bIsRecord = true;
+ }
+
+ if(m_sendthread.Start() < 0){
+ return -6;
+ }
+
+ if (JThread::Start() < 0){
+ m_bIsRecord = false;
+ return -6;
+ }
+
+ return 0;
+}
+
+void CVideoSender::Stop()
+{
+ if (!IsRunning())
+ return;
+
+ stopmutex.Lock();
+ stop = true;
+ stopmutex.Unlock();
+
+ //wait for two minute;
+ sleep(1);
+ if (JThread::IsRunning())
+ {
+#ifndef _WIN32_WCE
+ std::cerr << "RTPPollThread: Warning! Having to kill thread!" << std::endl;
+#endif // _WIN32_WCE
+ JThread::Kill();
+ }
+ stop = false;
+
+
+ //close file.
+ if(m_hFile){
+ fclose(m_hFile);
+ m_hFile = 0;
+ }
+
+ m_sendthread.Stop();
+
+ m_bIsRecord = false;
+}
+
+void CVideoSender::SetMode(VIDEOSENDERMODE mode)
+{
+ if(!IsInitialized())
+ return;
+
+ if(mode==ModeCapture || mode==ModeTransmit || mode==ModeNone){
+
+ m_modemutex.Lock();
+ m_mode = mode;
+ m_modemutex.Unlock();
+ }
+
+
+}
+
+void CVideoSender::Record(bool bInRecord /* =true */)
+{
+ if(!IsInitialized())
+ return ;
+
+ m_recordmutex.Lock();
+ m_bIsRecord = bInRecord;
+ m_recordmutex.Unlock();
+
+}
+
+
+
+void *CVideoSender::Thread()
+{
+ char * data;
+ int OutBufSzie;
+ int status;
+
+ JThread::ThreadStarted();
+
+ bool stopthread;
+ VIDEOSENDERMODE mode;
+// VideoPlayback fun;
+
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+
+ bool isrecord;
+ m_recordmutex.Lock();
+ isrecord = m_bIsRecord;
+ m_recordmutex.Unlock();
+
+
+ int64_t pre_time, cur_time;
+ useconds_t delay1;
+ pre_time = av_gettime();
+ if(m_vencoder.m_pCodecCtx->frame_rate!=0){
+ if(m_vencoder.m_pCodecCtx->frame_rate_base!=0)
+ delay1 = 1000000*m_vencoder.m_pCodecCtx->frame_rate_base/m_vencoder.m_pCodecCtx->frame_rate;
+ else
+ delay1 = 1000000/m_vencoder.m_pCodecCtx->frame_rate;
+ }
+ else{
+ delay1 = 40000;
+ }
+
+ delay1 = 40000;
+ cur_time = pre_time = av_gettime();
+ pre_time -= delay1;
+
+
+ int64_t nFrame;
+ int64_t rec_time,rec_start;
+ rec_start = cur_time;
+ rec_time = 0;
+ nFrame = 0;
+ while (!stopthread)
+ {
+ if(cur_time-pre_time>=delay1){
+/* cur_time = av_gettime();
+ delay = cur_time-pre_time;
+ if(delay < delay1){
+ usleep(delay1-delay);
+ pre_time = av_gettime();
+ }
+*/
+ pre_time = av_gettime();
+
+ m_modemutex.Lock();
+ mode = m_mode;
+ m_modemutex.Unlock();
+
+ if(mode==ModeNone){
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+
+ cur_time = av_gettime();
+ continue;
+ }
+// STARTTIME
+ status = m_vencoder.Capture(&data);
+// ENDTIME
+ if ((status) < 0)
+ {
+ printf("\nvideo: capture vital error.");
+ stopthread = true;
+ }
+ else{
+ if(mode==ModeCapture||mode==ModeTransmit){
+ int width, height;
+ m_vencoder.GetCapSize(width, height);
+ Playback((uint8_t*)data, width, height);
+
+ if(mode==ModeCapture){
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+
+ cur_time = av_gettime();
+ continue;
+ }
+ }
+
+ OutBufSzie = CVEncoder::V_En_OutBufSize;
+ if ((status = m_vencoder.EncodeProcess(data, m_pOutBuf, OutBufSzie)) < 0)
+ {
+ printf("\nvideo: encode vital error.");
+ stopthread = true;
+ }
+ else{
+ nFrame++;
+ if(status>0 && mode==ModeTransmit){
+// STARTTIME
+ m_sendthread.SendData(m_pOutBuf, status);
+// ENDTIME
+// printf("\n***************video send*************: %d bytes encoded.", status);
+ if(m_hFile!=0 && isrecord)
+ fwrite(m_pOutBuf+sizeof(VideoHeader), status-sizeof(VideoHeader), 1, m_hFile);
+ }
+
+ m_recordmutex.Lock();
+ isrecord = m_bIsRecord;
+ m_recordmutex.Unlock();
+
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+ }
+ }
+ }
+
+ cur_time = av_gettime();
+// printf("\nnFrame=%d,time=%d\n", nFrame, cur_time-rec_start);
+
+ }
+ printf("\nvideo capture thread stoped.\n");
+ return 0;
+}
+
+bool CVideoSender::AddDestination(const RTPIPv4Address &des)
+{
+ if(!IsInitialized())
+ return false;
+
+ if(m_sendthread.AddDestination(des)<0)
+ return false;
+
+ return true;
+}
+void CVideoSender::ClearDestinations()
+{
+ if(!IsInitialized())
+ return ;
+ m_sendthread.ClearDestinations();
+}
+
+
+
+//CStuVideoSender class.
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+CStuVideoSender::CStuVideoSender()
+{
+ stop = false;
+ m_bInit = 0;
+
+ m_mode = ModeNone;
+
+#if (defined(WIN32) || defined(_WIN32_WCE))
+ timeinit.Dummy();
+#endif // WIN32 || _WIN32_WCE
+}
+
+CStuVideoSender::~CStuVideoSender()
+{
+ //first stop thread, because m_pOutBuf is being used by Thread();
+ Stop();
+
+
+ //free buffer.
+ if(m_pOutBuf!=0)
+ free(m_pOutBuf);
+}
+
+bool CStuVideoSender::Init(int nHostPort)
+{
+ if(m_bInit)
+ return true;
+
+ if(!m_imagemutex.IsInitialized()){
+ if(m_imagemutex.Init() < 0)
+ return false;
+ }
+
+ //init rtpsession.
+ RTPSessionParams sessParams1;
+ sessParams1.SetOwnTimestampUnit(1.0 / 30.0); //30 video frames per second
+ sessParams1.SetUsePollThread(0); //background thread to call virtual callbacks - set by default, but just to be sure
+ sessParams1.SetMaximumPacketSize(MAX_PACKET_SIZE);
+ //setup transmission parameters
+ RTPUDPv4TransmissionParams transParams1;
+ transParams1.SetPortbase(nHostPort);
+ //CREATE THE SESSION
+ int status1 = m_fecrtpsession.Create(sessParams1, &transParams1);
+ if (status1){
+// ReportError(status1);
+ return false; //unable to create the session
+ }
+
+ //must set for fec SendFECPacket.
+ m_fecrtpsession.SetDefaultMark(true);
+ m_fecrtpsession.SetDefaultPayloadType(1);
+ m_fecrtpsession.SetDefaultTimestampIncrement(0);
+
+ if(m_pOutBuf==0){
+ m_pOutBuf = (uint8_t*)malloc(CVEncoder::V_En_OutBufSize);
+ if(m_pOutBuf==0){
+ return false;
+ }
+
+ }
+
+ //Init sencoder.
+ if(!m_vencoder.Init(CODEC_ID_MPEG1VIDEO)){
+ return false;
+ }
+
+ if (!m_modemutex.IsInitialized())
+ {
+ if (m_modemutex.Init() < 0)
+ return -2;
+ }
+
+
+ m_bInit = true;
+ return m_bInit;
+}
+
+bool CStuVideoSender::CreateXImage(Drawable parent, int x, int y, int width, int height)
+{
+ int screen_num;
+
+ if(!m_bInit)
+ return false;
+
+
+ CloseXImage();
+
+ m_imagemutex.Lock();
+
+ m_display = XOpenDisplay(NULL);
+ screen_num = DefaultScreen(m_display);
+
+
+ m_win = XCreateSimpleWindow(m_display, //display
+ parent, //çÃÂöçêÃÂÃÂ¥ÃÂã
+
+ x, y, width, height, //Ãâ¬Ã
ÂÃÂçÃ
ÂîÃÂ¥ÃÂÃÂÃ¥âÃ¥ðÃÂ1â¬7
+
+ 0, //ÃÅ¡Ã
žÃ¹Ã§ÃÂÃÂÃ¥îÃ
ÂÃ¥úÃ
Â
+ BlackPixel(m_display, screen_num), //ÃÂ¥ÃÂÃÂÃÅ ÃÂïÃÅ¡ÃÂò
+
+ 65535/20);//ÃÅ¡ÃÂÃÂÃÅ ÃÂïÃÅ¡ÃÂò
+
+ XMapWindow(m_display, m_win);
+ m_gc = DefaultGC(m_display, screen_num);
+
+ // Init GlobalVar.image
+ //
+ int imagewidth, imageheight;
+ m_vencoder.GetCapSize(imagewidth, imageheight);
+
+ m_image = XGetImage(m_display, //ÃÅ¡ÃÂ÷ÃÂ¥ÃÂÃÂÃÂ¥Ã
ÂÃÂÃÂ¥ÃÂÃÂÃ¥ñÃÂÃ¥ùÃÂÃÅ ÃÂÃÂÃÅ ÃÂÃ
žÃ§â¬úÃÂ¥ÃÂÃ
žÃÂ¥ÃÂÃÂ1â¬7
+ m_win,
+ 0, 0,
+ imagewidth, imageheight,
+ AllPlanes, ZPixmap);
+ if(!m_image){
+ printf("error\n");
+ m_imagemutex.Unlock();
+ return false;
+ }
+
+ m_imagemutex.Unlock();
+ return true;
+}
+
+void CStuVideoSender::CloseXImage()
+{
+ if(!m_bInit)
+ return ;
+
+ m_imagemutex.Lock();
+
+ if(m_image){
+ XDestroyImage(m_image);
+// m_image->f.destroy_image(m_image);
+ m_image = 0;
+ }
+
+ if(m_display){
+ if(m_win){
+ XUnmapWindow(m_display, m_win);
+ XClearWindow(m_display, m_win);
+ m_win = 0;
+ }
+ XCloseDisplay(m_display);
+ m_display = 0;
+ }
+
+ m_imagemutex.Unlock();
+}
+
+void CStuVideoSender::Playback(uint8_t* videodata, int width, int height)
+{
+ AVPicture pic_rgb24, pic_rgb32;
+
+ if(!m_bInit)
+ return;
+
+ m_imagemutex.Lock();
+
+ if(m_display && m_image && m_win){
+
+ avpicture_fill(&pic_rgb32, (uint8_t*)m_image->data, PIX_FMT_RGBA32,
+ width, height);
+ avpicture_fill(&pic_rgb24, videodata, PIX_FMT_BGR24,
+ width, height);
+
+ if(img_convert(&pic_rgb32, PIX_FMT_RGBA32, &pic_rgb24, PIX_FMT_BGR24,
+ width, height) < 0){
+ perror("Error pixel format conversion");
+ m_imagemutex.Unlock();
+ return ;
+ }
+
+
+ XPutImage(m_display, m_win, m_gc, m_image,
+ 0, 0, 0, 0,
+ width, height);
+ }
+
+ m_imagemutex.Unlock();
+ return;
+}
+
+
+int CStuVideoSender::Start(char* szFile /* =0 */, bool bIsRecord /* =false */)
+{
+ if(!m_bInit)
+ return -1;
+
+ if (JThread::IsRunning())
+ return 0;
+
+ if (!stopmutex.IsInitialized())
+ {
+ if (stopmutex.Init() < 0)
+ return -2;
+ }
+
+ stop = false;
+
+
+ if (JThread::Start() < 0){
+ return -6;
+ }
+
+ return 0;
+}
+
+void CStuVideoSender::Stop()
+{
+ if (!IsRunning())
+ return;
+
+ stopmutex.Lock();
+ stop = true;
+ stopmutex.Unlock();
+
+ //wait for two minute;
+ sleep(2);
+ if (JThread::IsRunning())
+ {
+#ifndef _WIN32_WCE
+ std::cerr << "RTPPollThread: Warning! Having to kill thread!" << std::endl;
+#endif // _WIN32_WCE
+ JThread::Kill();
+ }
+ stop = false;
+
+
+}
+
+void CStuVideoSender::SetMode(STUVIDEOSENDERMODE mode)
+{
+ if(!m_bInit)
+ return;
+
+ if(mode==ModeCapture || mode==ModeTransmit || mode==ModeNone){
+
+ m_modemutex.Lock();
+ m_mode = mode;
+ m_modemutex.Unlock();
+ }
+
+
+}
+
+
+void *CStuVideoSender::Thread()
+{
+ char * data;
+ int OutBufSzie;
+ int status;
+
+ JThread::ThreadStarted();
+
+ bool stopthread;
+ STUVIDEOSENDERMODE mode;
+// VideoPlayback fun;
+
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+
+ int64_t pre_time, cur_time;
+ useconds_t delay, delay1;
+
+ pre_time = av_gettime();
+ if(m_vencoder.m_pCodecCtx->frame_rate!=0){
+ if(m_vencoder.m_pCodecCtx->frame_rate_base!=0)
+ delay1 = 1000000*m_vencoder.m_pCodecCtx->frame_rate_base/m_vencoder.m_pCodecCtx->frame_rate;
+ else
+ delay1 = 1000000/m_vencoder.m_pCodecCtx->frame_rate;
+ }
+ else{
+ delay1 = 40000;
+ }
+// delay3 = 10000
+ while (!stopthread)
+ {
+
+ cur_time = av_gettime();
+ delay = cur_time-pre_time;
+ if(delay < delay1){
+ usleep(delay1-delay);
+ pre_time = av_gettime();
+ }
+
+ m_modemutex.Lock();
+ mode = m_mode;
+ m_modemutex.Unlock();
+
+ if(mode==ModeNone){
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+ continue;
+ }
+
+ if ((status = m_vencoder.Capture(&data)) < 0)
+ {
+ printf("\nvideo: capture vital error.");
+ stopthread = true;
+ }
+ else{
+ if(mode==ModeCapture||mode==ModeTransmit){
+ int width, height;
+ m_vencoder.GetCapSize(width, height);
+ Playback((uint8_t*)data, width, height);
+
+ if(mode==ModeCapture){
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+ continue;
+ }
+ }
+
+ OutBufSzie = CVEncoder::V_En_OutBufSize;
+ if ((status = m_vencoder.EncodeProcess(data, m_pOutBuf, OutBufSzie)) < 0)
+ {
+ printf("\nvideo: encode vital error.");
+ stopthread = true;
+ }
+ else{
+ if(status>0 && mode==ModeTransmit){
+ m_fecrtpsession.SendFECPacket(m_pOutBuf, status, 5000);
+ }
+
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+ }
+ }
+
+ }
+ printf("\nvideo record close");
+ return 0;
+}
+
+bool CStuVideoSender::AddDestination(const RTPIPv4Address &des)
+{
+ if(!m_bInit)
+ return false;
+
+ if(m_fecrtpsession.AddDestination(des)<0)
+ return false;
+
+ return true;
+}
+void CStuVideoSender::ClearDestinations()
+{
+ if(!m_bInit)
+ return ;
+ m_fecrtpsession.ClearDestinations();
+}
+
+//CVideoReceiver class.
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+CVideoReceiver::CVideoReceiver()
+{
+ m_bInit = false;
+}
+
+CVideoReceiver::~CVideoReceiver()
+{
+
+}
+
+bool CVideoReceiver::Init()
+{
+ if(m_bInit)
+ return m_bInit;
+
+
+ if(!m_vdecoder.Init(320, 240, CODEC_ID_MPEG1VIDEO)){
+ return false;
+ }
+
+
+ m_bInit = true;
+ return m_bInit;
+
+}
+
+bool CVideoReceiver::CreateXImage(Drawable parent, int x, int y, int width, int height)
+{
+ bool ret;
+ //init video decoder.
+
+ ret = m_vdecoder.CreateXImage(parent, x, y, width, height);
+
+ return ret;
+}
+
+void CVideoReceiver::CloseXImage()
+{
+ m_vdecoder.CloseXImage();
+}
+
+
+int CVideoReceiver::Start(int nHostPort)
+{
+ if(!m_bInit)
+ return -1;
+
+ if(IsActive())
+ return 0;
+
+ //init rtpsession.
+ RTPSessionParams sessParams1;
+ sessParams1.SetOwnTimestampUnit(1.0 / 30.0); //30 video frames per second
+ sessParams1.SetUsePollThread(1); //background thread to call virtual callbacks - set by default, but just to be sure
+ sessParams1.SetMaximumPacketSize(MAX_PACKET_SIZE);
+ //setup transmission parameters
+ RTPUDPv4TransmissionParams transParams1;
+ transParams1.SetPortbase(nHostPort);
+ //CREATE THE SESSION
+ int status1 = Create(sessParams1, &transParams1);
+ if (status1){
+// ReportError(status1);
+ return -2; //unable to create the session
+ }
+
+ return 0;
+}
+
+void CVideoReceiver::Stop()
+{
+ Destroy();
+}
+
+void CVideoReceiver::ProcessFrame(unsigned char* framedata, int framelen)
+{
+ //printf("\nVideo decodeproocessing(%d): %d bytes\n", m_usLatestVideoSeq, framelen);
+
+ pVideo= (VideoHeader*)framedata;
+ //printf("%d,%d\n",pVideo->width,pVideo->height);
+ if( pVideo->width!=m_vdecoder.m_width || pVideo->height != m_vdecoder.m_height){
+ m_vdecoder.ResetCodec( pVideo->width, pVideo->height);
+ }
+ m_vdecoder.DecodeProcess(framedata+sizeof(VideoHeader), framelen-sizeof(VideoHeader));
+}
+
+
+#ifdef HAVE_1394_CONFIG_H
+//C1394VEncoder class.
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+C1394VEncoder::C1394VEncoder()
+{
+ m_pFrameBuf = 0;
+ m_pFrame = 0;
+ m_pCodec = 0;
+ m_pCodecCtx = 0;
+ m_bInit = false;
+}
+
+C1394VEncoder::~C1394VEncoder()
+{
+ if(m_pFrameBuf){
+ free(m_pFrameBuf);
+ m_pFrameBuf = 0;
+ }
+
+
+ if(m_pFrame){
+ free(m_pFrame);
+ m_pFrame = 0;
+ }
+ if(m_pCodecCtx){
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+ m_bInit = false;
+
+}
+
+bool C1394VEncoder::Init(int width, int height, enum CodecID nCodecID /*=CODEC_ID_MPEG1VIDEO*/)
+{
+ m_bInit = false;
+ /*Init for encode*/
+ avcodec_init();
+ avcodec_register_all();
+
+ //new a frame object.
+ if(m_pFrame){
+ free(m_pFrame);
+ m_pFrame = 0;
+ }
+ m_pFrame = avcodec_alloc_frame();
+ if(m_pFrame==0){
+ return false;
+ }
+
+ /* find the video encoder */
+ m_pCodec = avcodec_find_encoder(nCodecID);
+ if (!m_pCodec) {
+ PErrorText("codec not found");
+
+ printf("\ncodec not found\n");
+ return false;
+ }
+
+ if(m_pCodecCtx){
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+
+ m_pCodecCtx = avcodec_alloc_context();
+ /* resolution must be a multiple of two */
+ m_pCodecCtx->width = width;
+ m_pCodecCtx->height = height;
+ /* frames per second */
+ m_pCodecCtx->frame_rate = V_CODEC_framerate;
+ m_pCodecCtx->frame_rate_base= V_CODEC_frame_rate_base;
+
+ m_pCodecCtx->bit_rate = 512*1024; // 1128kbps->512kbps
+ m_pCodecCtx->gop_size = V_CODEC_gop_size; /* emit one intra frame every ten frames */
+ m_pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
+ m_pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
+
+ /* open it */
+ if (avcodec_open(m_pCodecCtx, m_pCodec) < 0) {
+ PErrorText("could not open codec");
+ return false;
+ }
+
+ //malloc outbuf.
+ if(m_pFrameBuf){
+ free(m_pFrameBuf);
+ m_pFrameBuf = 0;
+ }
+
+ int image_size = avpicture_get_size (PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+
+ m_pFrameBuf = (uint8_t*)malloc(image_size);
+ if(m_pFrameBuf == 0){
+ PErrorText("FrameBuf malloc failed!");
+ return false;
+ }
+ /*Init for encode*/
+
+
+ avpicture_fill ((AVPicture*)m_pFrame, m_pFrameBuf, PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+ m_pFrame->type = FF_BUFFER_TYPE_SHARED;
+// printf("\nWarning:m_pFrame->type is not seted!!!!!!!!!!!!!!!!!!!!!!!!\n");
+
+ m_bInit = true;
+ return true;
+}
+
+
+int C1394VEncoder::EncodeProcess(char *frameaddress, uint8_t *pOutBuf, int nOutsize)
+{
+ if(!m_bInit)
+ return -1;
+
+ if(nOutsize<V_En_OutBufSize){
+ return -2;
+ }
+
+ avpicture_fill(&m_pic_rgb, (uint8_t *)frameaddress, PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height);
+ avpicture_fill((AVPicture*)m_pFrame, m_pFrameBuf, PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+
+ if (img_convert ((AVPicture*)m_pFrame, PIX_FMT_YUV420P,
+ &m_pic_rgb, PIX_FMT_RGB24, m_pCodecCtx->width, m_pCodecCtx->height) < 0) {
+ fprintf (stderr, "xtoffmpeg.XImageToFFMPEG(): pixel format conversion not handled ... aborting\n");
+ return -3;
+ }
+
+ m_VideoHeader.width=m_pCodecCtx->width;
+ m_VideoHeader.height=m_pCodecCtx->height;
+ memcpy((char *)pOutBuf,&m_VideoHeader, sizeof(VideoHeader));
+
+ int iii = avcodec_encode_video(m_pCodecCtx, pOutBuf+sizeof(VideoHeader), nOutsize, m_pFrame);
+
+ if(iii<=0)
+ return -4;
+
+ return iii+sizeof(VideoHeader);
+}
+
+bool C1394VEncoder::GetCapSize(int &width, int &height)
+{
+ if(!m_bInit)
+ return false;
+
+ width = m_pCodecCtx->width;
+ height = m_pCodecCtx->height;
+
+ return true;
+}
+
+
+
+void C1394VEncoder::GetColorInfo (XImage *image, ColorInfo *ci /* return struct */)
+{
+ unsigned long red_mask, green_mask, blue_mask, alpha_mask;
+ // the shifts are unsigned longs as well
+
+ if (!ci)
+ return;
+
+ // setting shifts and bit_depths to zero
+ ci->red_shift = ci->green_shift = ci->blue_shift = ci->alpha_shift = 0;
+ ci->red_bit_depth = ci->green_bit_depth = ci->blue_bit_depth =
+ ci->alpha_bit_depth = 0;
+
+ red_mask = image->red_mask;
+ if (red_mask > 0) {
+ // shift red_mask to the right till all empty bits have been
+ // shifted out and count how many they were
+ while ((red_mask & 0x01) == 0) {
+ red_mask >>= 1;
+ ci->red_shift++;
+ }
+ // count how many bits are set in the mask = depth
+ while ((red_mask & 0x01) == 1) {
+ red_mask >>= 1;
+ ci->red_bit_depth++;
+ }
+ }
+
+ ci->red_max_val = (1 << ci->red_bit_depth) - 1;
+
+ green_mask = image->green_mask;
+ if (green_mask > 0) {
+ while ((green_mask & 0x01) == 0) {
+ green_mask >>= 1;
+ ci->green_shift++;
+ }
+ while ((green_mask & 0x01) == 1) {
+ green_mask >>= 1;
+ ci->green_bit_depth++;
+ }
+ }
+ ci->green_max_val = (1 << ci->green_bit_depth) - 1;
+
+ blue_mask = image->blue_mask;
+ if (blue_mask > 0) {
+ while ((blue_mask & 0x01) == 0) {
+ blue_mask >>= 1;
+ ci->blue_shift++;
+ }
+ while ((blue_mask & 0x01) == 1) {
+ blue_mask >>= 1;
+ ci->blue_bit_depth++;
+ }
+ }
+ ci->blue_max_val = (1 << ci->blue_bit_depth) - 1;
+
+ /* over all max values */
+ // whatever they are good for
+ ci->max_val = max (ci->red_max_val, ci->green_max_val);
+ ci->max_val = max (ci->blue_max_val, ci->max_val);
+ ci->bit_depth = max (ci->red_bit_depth, ci->green_bit_depth);
+ ci->bit_depth = max (ci->blue_bit_depth, ci->bit_depth);
+ if (image->bits_per_pixel > image->depth) {
+ /* alpha? */
+ // this seems to not reflect X's ignorance of alpha in its
+ // masks
+ ci->alpha_mask = ~
+ (image->red_mask | image->blue_mask | image->green_mask);
+ alpha_mask = ci->alpha_mask;
+ if (alpha_mask > 0) {
+ while ((alpha_mask & 0x01) == 0) {
+ alpha_mask >>= 1;
+ ci->alpha_shift++;
+ }
+ while ((alpha_mask & 0x01) == 1) {
+ alpha_mask >>= 1;
+ ci->alpha_bit_depth++;
+ }
+ }
+ ci->alpha_max_val = (1 << ci->alpha_bit_depth) - 1;
+ }
+}
+
+//C1394VideoSender class.
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+C1394VideoSender::C1394VideoSender() : m_sendthread(SendBufSize)
+{
+ stop = false;
+ m_bIsRecord = false;
+ m_bInit = 0;
+
+ m_pOutBuf = 0;
+ m_hFile = 0;
+ m_mode = ModeNone;
+ m_p1394reader = 0;
+ m_pCapBuf = 0;
+
+ if(!m_initmutex.IsInitialized()){
+ m_initmutex.Init();
+ }
+
+ m_display = 0;
+ m_image = 0;
+ m_win = 0;
+ m_d = 0;
+}
+
+C1394VideoSender::~C1394VideoSender()
+{
+ //first stop thread, because m_pOutBuf is being used by Thread();
+ Stop();
+
+ //close file.
+ if(m_hFile){
+ fclose(m_hFile);
+ m_hFile = 0;
+ }
+
+ //free buffer.
+ if(m_pOutBuf!=0){
+ free(m_pOutBuf);
+ m_pOutBuf = 0;
+ }
+
+ // for image
+ if(m_image){
+ XDestroyImage(m_image);
+ m_image = 0;
+ }
+
+ if(m_display){
+ if(m_win){
+ XUnmapWindow(m_display, m_win);
+ XClearWindow(m_display, m_win);
+ m_win = 0;
+ }
+
+ if(m_d){
+ XClearWindow(m_display, m_d);
+ m_d = 0;
+ }
+
+ XCloseDisplay(m_display);
+ m_display = 0;
+ }
+}
+
+#define MAX_PACKET_SIZE 10*1024
+bool C1394VideoSender::Init(int nHostPort)
+{
+ m_initmutex.Lock();
+ m_bInit = false;
+
+ if(!m_imagemutex.IsInitialized()){
+ if(m_imagemutex.Init() < 0){
+ m_initmutex.Unlock();
+ return false;
+ }
+ }
+
+ if(!m_sendthread.Init(nHostPort)){
+
+ m_initmutex.Unlock();
+ return false;
+ }
+
+ if(m_pOutBuf==0){
+ m_pOutBuf = (uint8_t*)malloc(C1394VEncoder::V_En_OutBufSize);
+ if(m_pOutBuf==0){
+ m_initmutex.Unlock();
+ return false;
+ }
+
+ }
+
+ //Init sencoder.
+ if(!m_vencoder.Init(VideoWidth, VideoHeight, CODEC_ID_MPEG1VIDEO)){
+ m_initmutex.Unlock();
+ return false;
+ }
+
+ if (!m_modemutex.IsInitialized())
+ {
+ if (m_modemutex.Init() < 0){
+ m_initmutex.Unlock();
+ return false;
+ }
+
+ }
+
+
+ m_bIsRecord = false;
+
+ m_bInit = true;
+ m_initmutex.Unlock();
+ return true;
+}
+
+bool C1394VideoSender::IsInitialized()
+{
+ bool b;
+
+ m_initmutex.Lock();
+ b = m_bInit;
+ m_initmutex.Unlock();
+
+ return b;
+}
+
+
+bool C1394VideoSender::CreateXImage(Drawable parent, int x, int y, int width, int height)
+{
+ int screen_num;
+
+
+ if(!IsInitialized())
+ return false;
+
+ CloseXImage();
+
+ m_imagemutex.Lock();
+
+ m_display = XOpenDisplay(NULL);
+ screen_num = DefaultScreen(m_display);
+
+
+ m_win = XCreateSimpleWindow(m_display, //display
+ parent, //çÃÂöçêÃÂÃÂ¥ÃÂã
+
+ x, y, width, height, //Ãâ¬Ã
ÂÃÂçÃ
ÂîÃÂ¥ÃÂÃÂÃ¥âÃ¥ðÃÂ1â¬7
+
+ 0, //ÃÅ¡Ã
žÃ¹Ã§ÃÂÃÂÃ¥îÃ
ÂÃ¥úÃ
Â
+ BlackPixel(m_display, screen_num), //ÃÂ¥ÃÂÃÂÃÅ ÃÂïÃÅ¡ÃÂò
+
+ 65535/20);//ÃÅ¡ÃÂÃÂÃÅ ÃÂïÃÅ¡ÃÂò
+
+ XMapWindow(m_display, m_win);
+ m_gc = DefaultGC(m_display, screen_num);
+
+ int imagewidth, imageheight;
+ m_vencoder.GetCapSize(imagewidth, imageheight);
+
+ m_d = RootWindow(m_display, screen_num);
+
+ m_image = XGetImage(m_display, //ÃÅ¡ÃÂ÷ÃÂ¥ÃÂÃÂÃÂ¥Ã
ÂÃÂÃÂ¥ÃÂÃÂÃ¥ñÃÂÃ¥ùÃÂÃÅ ÃÂÃÂÃÅ ÃÂÃ
žÃ§â¬úÃÂ¥ÃÂÃ
žÃÂ¥ÃÂÃÂ1â¬7
+ m_d,
+ 0, 0,
+ imagewidth, imageheight,
+ AllPlanes, ZPixmap);
+ if(!m_image){
+ PErrorText("GetImage error");
+ m_imagemutex.Unlock();
+ return false;
+ }
+
+ m_imagemutex.Unlock();
+ return true;
+}
+
+void C1394VideoSender::CloseXImage()
+{
+
+ if(!IsInitialized())
+ return ;
+
+ m_imagemutex.Lock();
+
+ if(m_image){
+ XDestroyImage(m_image);
+ m_image = 0;
+ }
+
+ if(m_display){
+ if(m_win){
+ XUnmapWindow(m_display, m_win);
+ XClearWindow(m_display, m_win);
+ m_win = 0;
+ }
+
+ if(m_d){
+ XClearWindow(m_display, m_d);
+ m_d = 0;
+ }
+
+ XCloseDisplay(m_display);
+ m_display = 0;
+ }
+
+ m_imagemutex.Unlock();
+}
+
+void C1394VideoSender::Playback(uint8_t* videodata)
+{
+ AVPicture pic_rgb24, pic_rgb32;
+ int width, height;
+
+ if(!IsInitialized())
+ return;
+
+ m_vencoder.GetCapSize(width, height);
+
+ m_imagemutex.Lock();
+
+// printf("****************%d\n",CVDecoder::input_pixfmt);
+ if(m_display && m_image && m_win){
+
+ avpicture_fill(&pic_rgb32, (uint8_t*)m_image->data, CVDecoder::input_pixfmt,
+ width, height);
+ avpicture_fill(&pic_rgb24, videodata, PIX_FMT_RGB24,
+ width, height);
+
+ if(img_convert(&pic_rgb32, CVDecoder::input_pixfmt, &pic_rgb24, PIX_FMT_RGB24,
+ width, height) < 0){
+ PErrorText("Error pixel format conversion");
+ m_imagemutex.Unlock();
+ return ;
+ }
+
+
+ XPutImage(m_display, m_win, m_gc, m_image,
+ 0, 0, 0, 0,
+ width, height);
+ }
+
+ m_imagemutex.Unlock();
+ return;
+}
+
+int C1394VideoSender::Start(char* szFile /* =0 */, bool bIsRecord /* =false */)
+{
+
+ if(!IsInitialized())
+ return -1;
+
+ if (JThread::IsRunning())
+ return 0;
+
+ if (!stopmutex.IsInitialized())
+ {
+ if (stopmutex.Init() < 0)
+ return -2;
+ }
+
+ stop = false;
+
+ if (!m_recordmutex.IsInitialized())
+ {
+ if (m_recordmutex.Init() < 0)
+ return -2;
+ }
+
+ m_bIsRecord = bIsRecord;
+
+
+ if(!StartCapture()){
+ return -7;
+ }
+
+ if( szFile != 0){
+ if(m_hFile){
+ fclose(m_hFile);
+ m_hFile = 0;
+ }
+
+ m_hFile = fopen(szFile, "wb");
+ if(m_hFile==0){
+ m_bIsRecord = false;
+ return -3;
+ }
+
+ }
+
+ if(m_sendthread.Start() < 0){
+ return -6;
+ }
+
+ if (JThread::Start() < 0){
+ m_bIsRecord = false;
+ return -6;
+ }
+
+ return 0;
+}
+
+void C1394VideoSender::Stop()
+{
+ if (!IsRunning())
+ return;
+
+ stopmutex.Lock();
+ stop = true;
+ stopmutex.Unlock();
+
+ //wait for two minute;
+
+// sleep(1);
+// if (JThread::IsRunning())
+// {
+// JThread::Kill();
+// }
+
+ int count=0;
+ while(1){
+ if(count>=100){
+ if (JThread::IsRunning())
+ {
+ JThread::Kill();
+ }
+ break;
+ }
+
+ if(JThread::IsRunning()){
+ count++;
+ usleep(10000);
+ continue;
+ }
+
+ break;
+ }
+
+ stop = false;
+
+ //close file.
+ if(m_hFile){
+ fclose(m_hFile);
+ m_hFile = 0;
+ }
+
+ m_sendthread.Stop();
+
+ StopCapture();
+ m_bIsRecord = false;
+}
+
+void C1394VideoSender::SetMode(_1394VIDEO_SEND_MODE mode)
+{
+
+ if(!IsInitialized())
+ return;
+
+ if(mode==ModeCapture || mode==ModeTransmit || mode==ModeNone){
+
+ m_modemutex.Lock();
+ m_mode = mode;
+ m_modemutex.Unlock();
+ }
+
+
+}
+
+void C1394VideoSender::Record(bool bInRecord /* =true */)
+{
+
+ if(!IsInitialized())
+ return;
+
+ m_recordmutex.Lock();
+ m_bIsRecord = bInRecord;
+ m_recordmutex.Unlock();
+
+}
+
+void *C1394VideoSender::Thread()
+{
+ char * data;
+ int OutBufSzie;
+ int status;
+
+ JThread::ThreadStarted();
+
+ bool stopthread;
+ _1394VIDEO_SEND_MODE mode;
+// VideoPlayback fun;
+
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+
+ bool isrecord;
+ m_recordmutex.Lock();
+ isrecord = m_bIsRecord;
+ m_recordmutex.Unlock();
+
+
+ int64_t pre_time, cur_time;
+ useconds_t delay, delay1;
+ pre_time = av_gettime();
+ if(m_vencoder.m_pCodecCtx->frame_rate!=0){
+ if(m_vencoder.m_pCodecCtx->frame_rate_base!=0)
+ delay1 = 1000000*m_vencoder.m_pCodecCtx->frame_rate_base/m_vencoder.m_pCodecCtx->frame_rate;
+ else
+ delay1 = 1000000/m_vencoder.m_pCodecCtx->frame_rate;
+ }
+ else{
+ delay1 = 62500; // 1000000/16 = 62500
+ }
+
+ // sleep for sync
+ if(delay_time > 0){
+ sleep(delay_time);
+ }
+
+ // for utility rate of CPU
+ cur_time = pre_time = av_gettime();
+ pre_time -= delay1;
+
+ // for compensate.
+ int64_t nFrame=0;
+ int64_t rec_time=0;
+ int64_t rec_start;
+ rec_start = av_gettime();
+ while (!stopthread)
+ {
+ delay = cur_time - pre_time;
+ if(delay < delay1){
+ usleep(delay1 - delay);
+ }
+ pre_time = av_gettime();
+
+
+ m_modemutex.Lock();
+ mode = m_mode;
+ m_modemutex.Unlock();
+
+ if(mode==ModeNone){
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+
+ rec_start = cur_time = av_gettime();
+ nFrame = 0;
+ cur_time = av_gettime();
+ continue;
+ }
+
+ if ((status = Capture((uint8_t**)&data)) < 0)
+ {
+ printf("\nvideo: capture vital error.");
+ stopthread = true;
+ continue;
+ }
+ else{
+ if(mode==ModeCapture||mode==ModeTransmit){
+// int width, height;
+// m_vencoder.GetCapSize(width, height);
+ Playback((uint8_t*)data);
+
+ if(mode==ModeCapture){
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+
+ rec_start = cur_time = av_gettime();
+ nFrame = 0;
+ cur_time = av_gettime();
+ continue;
+ }
+ }
+
+ OutBufSzie = C1394VEncoder::V_En_OutBufSize;
+ if ((status = m_vencoder.EncodeProcess(data, m_pOutBuf, OutBufSzie)) < 0)
+ {
+ printf("\nvideo: encode vital error.");
+ stopthread = true;
+ continue;
+ }
+ else{
+ if(status>0 && mode==ModeTransmit){
+ m_sendthread.SendData(m_pOutBuf, status);
+// printf("\n-----------------video send------------------: %d bytes encoded.", status);
+ if(m_hFile!=0 && isrecord){
+ nFrame++;
+ fwrite(m_pOutBuf+sizeof(VideoHeader), status-sizeof(VideoHeader), 1, m_hFile);
+
+ //add up rec_time;
+ rec_time = av_gettime()-rec_start;
+ int i;
+ for(i=0;rec_time>nFrame*delay1;nFrame++, i++){
+ // printf("(%d): rec_time=%ld, ", i, rec_time, nFrame);
+ // printf("nFrame=%d\n", nFrame);
+ if( (status = m_vencoder.EncodeProcess(data, m_pOutBuf, OutBufSzie) )<0){
+ printf("\nvideo: encode vital error.");
+ stopthread = true;
+ printf("\nvideo capture thread stoped by EncodeProcess error!\n");
+ return 0;
+ }
+ if(status>0){
+ fwrite(m_pOutBuf+sizeof(VideoHeader), status-sizeof(VideoHeader), 1, m_hFile);
+ //printf("1394 frame conpensation .... \n");
+ }
+ }
+
+ //printf("\n1394 video rec_time=%ld,", rec_time);
+ //printf("Frame=%ld\n", nFrame);
+
+ }
+ else{
+ rec_start = av_gettime();
+ nFrame = 0;
+ }
+
+ }
+
+// m_recordmutex.Lock();
+// isrecord = m_bIsRecord;
+// m_recordmutex.Unlock();
+
+// stopmutex.Lock();
+// stopthread = stop;
+// stopmutex.Unlock();
+ }
+ }
+
+ cur_time = av_gettime();
+ }
+
+ m_recordmutex.Lock();
+ isrecord = m_bIsRecord;
+ m_recordmutex.Unlock();
+
+ stopmutex.Lock();
+ stopthread = stop;
+ stopmutex.Unlock();
+
+ // printf("\n--------------nFrame=%d:%d \n", nFrame, (int)rec_time);
+
+ printf("\nvideo capture thread stoped.\n");
+ return 0;
+}
+
+bool C1394VideoSender::AddDestination(const RTPIPv4Address &des)
+{
+
+ if(!IsInitialized())
+ return false;
+
+ if(m_sendthread.AddDestination(des)<0)
+ return false;
+
+ return true;
+}
+void C1394VideoSender::ClearDestinations()
+{
+
+ if(!IsInitialized())
+ return;
+
+ m_sendthread.ClearDestinations();
+}
+
+
+bool C1394VideoSender::StartCapture()
+{
+ StopCapture();
+
+ m_pCapBuf = (void*) malloc(FRAME_MAX_WIDTH*FRAME_MAX_HEIGHT*4);
+ if(m_pCapBuf==0)
+ return false;
+
+ m_p1394reader = new raw1394Reader(0, 63, 5);
+
+ if(m_p1394reader == 0)
+ return false;
+
+
+ if(!m_p1394reader->StartThread()){
+ delete m_p1394reader;
+ m_p1394reader = 0;
+ return false;
+ }
+
+ return true;
+
+}
+
+void C1394VideoSender::StopCapture()
+{
+
+ if(m_p1394reader){
+ m_p1394reader->StopThread();
+ m_p1394reader->StopReceive();
+ m_p1394reader->Close();
+ delete m_p1394reader;
+ m_p1394reader = 0;
+ }
+
+ if(m_pCapBuf){
+ free(m_pCapBuf);
+ m_pCapBuf = 0;
+ }
+}
+
+bool C1394VideoSender::IsHaved1394Video()
+{
+
+ bool res = false;
+/*
+ if(IsInitialized()){
+ if(IsRunning())
+ }
+ else{
+
+ }
+*/
+
+ return res;
+}
+
+int C1394VideoSender::Capture(uint8_t** data)
+{
+ Frame *pFrame;
+ m_p1394reader->WaitForAction();
+ pFrame = m_p1394reader->GetFrame();
+
+ pFrame->ExtractRGB(m_pCapBuf);
+ Scale();
+ m_p1394reader->DoneWithFrame(pFrame);
+
+ *data = (uint8_t*)m_pCapBuf;
+ return 0;
+
+}
+
+void C1394VideoSender::Scale()
+{
+ int width, height;
+ GdkPixbuf *original_pixbuf = 0;
+ GdkPixbuf *scaled_pixbuf = 0;
+
+ width=0,height=0;
+ m_vencoder.GetCapSize(width, height);
+ if(width==720 && height == 576)
+ return;
+ original_pixbuf = gdk_pixbuf_new_from_data((const guchar*)m_pCapBuf, // const guchar *data
+ GDK_COLORSPACE_RGB, // GdkColorspace colorspace
+ FALSE, // gboolean has_alpha
+ 8, // int bits_per_sample
+ 720, // int width
+ 576, // int height
+ 720*3, // int rowstride
+ NULL,// GdkPixbufDestroyNotify destroy_fn
+ NULL); // gpointer destroy_fn_data
+ if(original_pixbuf == 0){
+ g_object_unref(original_pixbuf);
+ printf("\n gdk_pixbuf_new_from_data failed!! \n");
+ return ;
+ }
+
+ scaled_pixbuf = gdk_pixbuf_scale_simple(original_pixbuf, width, height, GDK_INTERP_BILINEAR);
+
+ if(scaled_pixbuf == 0){
+ g_object_unref(scaled_pixbuf);
+ printf("\n gdk_pixbuf_scale_simple failed!!! \n");
+ return ;
+ }
+
+ memcpy(m_pCapBuf, (uint8_t*)gdk_pixbuf_get_pixels(scaled_pixbuf), width*height*3);
+ g_object_unref(original_pixbuf);
+ g_object_unref(scaled_pixbuf);
+
+}
+#endif // HAVE_1394_CONFIG_H
+
+//CV4LVEncoder class.
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+CV4LVEncoder::CV4LVEncoder()
+{
+ m_pFrameBuf = 0;
+ m_pFrame = 0;
+ m_pCodec = 0;
+ m_pCodecCtx = 0;
+ m_bInit = false;
+// for test encode.
+// pFile = fopen("video.mpg", "wb+");
+}
+
+CV4LVEncoder::~CV4LVEncoder()
+{
+// for test encode.
+// if(pFile!=0)
+// fclose(pFile);
+
+
+ if(m_pFrameBuf){
+ free(m_pFrameBuf);
+ m_pFrameBuf = 0;
+ }
+
+
+ if(m_pFrame){
+ free(m_pFrame);
+ m_pFrame = 0;
+ }
+ if(m_pCodecCtx){
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+ m_bInit = false;
+
+}
+
+bool CV4LVEncoder::Init(int width, int height, enum CodecID nCodecID /*=CODEC_ID_MPEG1VIDEO*/)
+{
+ m_bInit = false;
+ /*Init for encode*/
+ avcodec_init();
+ avcodec_register_all();
+
+ //new a frame object.
+ if(m_pFrame){
+ free(m_pFrame);
+ m_pFrame = 0;
+ }
+ m_pFrame = avcodec_alloc_frame();
+ if(m_pFrame==0){
+ return false;
+ }
+
+ /* find the video encoder */
+ m_pCodec = avcodec_find_encoder(nCodecID);
+ if (!m_pCodec) {
+ PErrorText("codec not found");
+
+ printf("\ncodec not found\n");
+ return false;
+ }
+
+ if(m_pCodecCtx){
+ avcodec_close(m_pCodecCtx);
+ m_pCodecCtx = 0;
+ }
+
+ m_pCodecCtx = avcodec_alloc_context();
+ /* resolution must be a multiple of two */
+ m_pCodecCtx->width = width;
+ m_pCodecCtx->height = height;
+ /* frames per second */
+ m_pCodecCtx->frame_rate = V_CODEC_framerate;
+ m_pCodecCtx->frame_rate_base= V_CODEC_frame_rate_base;
+
+ m_pCodecCtx->bit_rate = 512*1024; //1128kbps->512kbps
+ m_pCodecCtx->gop_size = V_CODEC_gop_size; /* emit one intra frame every ten frames */
+ m_pCodecCtx->codec_type = CODEC_TYPE_VIDEO;
+ m_pCodecCtx->pix_fmt = PIX_FMT_YUV420P;
+
+ /* open it */
+ if (avcodec_open(m_pCodecCtx, m_pCodec) < 0) {
+ PErrorText("could not open codec");
+ return false;
+ }
+
+ //malloc outbuf.
+ if(m_pFrameBuf){
+ free(m_pFrameBuf);
+ m_pFrameBuf = 0;
+ }
+
+ int image_size = avpicture_get_size (PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+
+ m_pFrameBuf = (uint8_t*)malloc(image_size);
+ if(m_pFrameBuf == 0){
+ PErrorText("FrameBuf malloc failed!");
+ return false;
+ }
+ /*Init for encode*/
+
+
+ avpicture_fill ((AVPicture*)m_pFrame, m_pFrameBuf, PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+ m_pFrame->type = FF_BUFFER_TYPE_SHARED;
+// printf("\nWarning:m_pFrame->type is not seted!!!!!!!!!!!!!!!!!!!!!!!!\n");
+
+ m_bInit = true;
+ return true;
+}
+
+// for test encode.
+//void SaveVideoFile(char* buf, int bufsize)
+//{
+// fwrite(buf, bufsize, 1, pFile);
+// return;
+//}
+int CV4LVEncoder::EncodeProcess(char *frameaddress, uint8_t *pOutBuf, int nOutsize)
+{
+
+ if(!m_bInit)
+ return -1;
+
+ if(nOutsize<V_En_OutBufSize){
+ return -2;
+ }
+
+ avpicture_fill(&m_pic_rgb, (uint8_t *)frameaddress, PIX_FMT_BGR24, m_pCodecCtx->width, m_pCodecCtx->height);
+ avpicture_fill((AVPicture*)m_pFrame, m_pFrameBuf, PIX_FMT_YUV420P, m_pCodecCtx->width, m_pCodecCtx->height);
+
+ if (img_convert ((AVPicture*)m_pFrame, PIX_FMT_YUV420P,
+ &m_pic_rgb, PIX_FMT_BGR24, m_pCodecCtx->width, m_pCodecCtx->height) < 0) {
+ fprintf (stderr, "xtoffmpeg.XImageToFFMPEG(): pixel format conversion not handled ... aborting\n");
+ return -3;
+ }
+
+ m_VideoHeader.width=m_pCodecCtx->width;
+ m_VideoHeader.height=m_pCodecCtx->height;
+ memcpy((char *)pOutBuf,&m_VideoHeader, sizeof(VideoHeader));
+
+ int iii = avcodec_encode_video(m_pCodecCtx, pOutBuf+sizeof(VideoHeader), nOutsize, m_pFrame);
+
+ if(iii<=0)
+ return -4;
+
+ return iii+sizeof(VideoHeader);
+}
+
+bool CV4LVEncoder::GetCapSize(int &width, int &height)
+{
+ if(!m_bInit)
+ return false;
+
+ width = m_pCodecCtx->width;
+ height = m_pCodecCtx->height;
+
+ return true;
+}
+
+
+
+void CV4LVEncoder::GetColorInfo (XImage *image, ColorInfo *ci /* return struct */)
+{
+ unsigned long red_mask, green_mask, blue_mask, alpha_mask;
+ // the shifts are unsigned longs as well
+
+ if (!ci)
+ return;
+
+ // setting shifts and bit_depths to zero
+ ci->red_shift = ci->green_shift = ci->blue_shift = ci->alpha_shift = 0;
+ ci->red_bit_depth = ci->green_bit_depth = ci->blue_bit_depth =
+ ci->alpha_bit_depth = 0;
+
+ red_mask = image->red_mask;
+ if (red_mask > 0) {
+ // shift red_mask to the right till all empty bits have been
+ // shifted out and count how many they were
+ while ((red_mask & 0x01) == 0) {
+ red_mask >>= 1;
+ ci->red_shift++;
+ }
+ // count how many bits are set in the mask = depth
+ while ((red_mask & 0x01) == 1) {
+ red_mask >>= 1;
+ ci->red_bit_depth++;
+ }
+ }
+
+ ci->red_max_val = (1 << ci->red_bit_depth) - 1;
+
+ green_mask = image->green_mask;
+ if (green_mask > 0) {
+ while ((green_mask & 0x01) == 0) {
+ green_mask >>= 1;
+ ci->green_shift++;
+ }
+ while ((green_mask & 0x01) == 1) {
+ green_mask >>= 1;
+ ci->green_bit_depth++;
+ }
+ }
+ ci->green_max_val = (1 << ci->green_bit_depth) - 1;
+
+ blue_mask = image->blue_mask;
+ if (blue_mask > 0) {
+ while ((blue_mask & 0x01) == 0) {
+ blue_mask >>= 1;
+ ci->blue_shift++;
+ }
+ while ((blue_mask & 0x01) == 1) {
+ blue_mask >>= 1;
+ ci->blue_bit_depth++;
+ }
+ }
+ ci->blue_max_val = (1 << ci->blue_bit_depth) - 1;
+
+ /* over all max values */
+ // whatever they are good for
+ ci->max_val = max (ci->red_max_val, ci->green_max_val);
+ ci->max_val = max (ci->blue_max_val, ci->max_val);
+ ci->bit_depth = max (ci->red_bit_depth, ci->green_bit_depth);
+ ci->bit_depth = max (ci->blue_bit_depth, ci->bit_depth);
+ if (image->bits_per_pixel > image->depth) {
+ /* alpha? */
+ // this seems to not reflect X's ignorance of alpha in its
+ // masks
+ ci->alpha_mask = ~
+ (image->red_mask | image->blue_mask | image->green_mask);
+ alpha_mask = ci->alpha_mask;
+ if (alpha_mask > 0) {
+ while ((alpha_mask & 0x01) == 0) {
+ alpha_mask >>= 1;
+ ci->alpha_shift++;
+ }
+ while ((alpha_mask & 0x01) == 1) {
+ alpha_mask >>= 1;
+ ci->alpha_bit_depth++;
+ }
+ }
+ ci->alpha_max_val = (1 << ci->alpha_bit_depth) - 1;
+ }
+}
+
+
+//CV4LVideoSender class.
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+CV4LVideoSender::CV4LVideoSender() : m_sendthread(SendBufSize)
+{
+ stop = false;
+ m_bIsRecord = false;
+ m_bInit = 0;
+
+ m_pOutBuf = 0;
+ m_hFile = 0;
+ m_mode = ModeNone;
+ m_pV4Ldev = 0;
+
+ if(!m_initmutex.IsInitialized()){
+ m_initmutex.Init();
+ }
+
+ m_display = 0;
+ m_win = 0;
+ m_d = 0;
+ m_image = 0;
+
+
+}
+
+CV4LVideoSender::~CV4LVideoSender()
+{
+ //first stop thread, because m_pOutBuf is being used by Thread();
+ Stop();
+
+ //close file.
+ if(m_hFile){
+ fclose(m_hFile);
+ m_hFile = 0;
+ }
+
+ //free buffer.
+ if(m_pOutBuf!=0){
+ free(m_pOutBuf);
+ m_pOutBuf = 0;
+ }
+
+ // for image
+ if(m_image){
+ XDestroyImage(m_image);
+ m_image = 0;
+ }
+
+ if(m_display){
+ if(m_win){
+ XUnmapWindow(m_display, m_win);
+ XClearWindow(m_display, m_win);
+ m_win = 0;
+ }
+
+ if(m_d){
+ XClearWindow(m_display, m_d);
+ m_d = 0;
+ }
+
+ XCloseDisplay(m_display);
+ m_display = 0;
+ }
+
+ CloseVideo();
+}
+
+
+bool CV4LVideoSender::Init(int nHostPort)
+{
+ m_initmutex.Lock();
+ m_bInit = false;
+
+ if(!m_imagemutex.IsInitialized()){
+ if(m_imagemutex.Init() < 0){
+ m_initmutex.Unlock();
+ return false;
+ }
+ }
+
+
+ if(!OpenVideo()){
+ m_initmutex.Unlock();
+ return false;
+ }
+
+ if(!m_sendthread.Init(nHostPort)){
+
+ m_initmutex.Unlock();
+ return false;
+ }
+
+ if(m_pOutBuf==0){
+ m_pOutBuf = (uint8_t*)malloc(CV4LVEncoder::V_En_OutBufSize);
+ if(m_pOutBuf==0){
+ m_initmutex.Unlock();
+ return false;
+ }
+
+ }
+
+ //Init sencoder.
+ if(!m_vencoder.Init(VideoWidth, VideoHeight, CODEC_ID_MPEG1VIDEO)){
+ m_initmutex.Unlock();
[... 1096 lines stripped ...]