1 /*==================================================================
3 ! mardrone application AR-Drone for MeeGo
5 ! Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
8 ! Author:Kate Alhola kate.alhola@nokia.com
10 ! GNU Lesser General Public License Usage
11 ! This file may be used under the terms of the GNU Lesser
12 ! General Public License version 2.1 as published by the Free Software
13 ! Foundation and appearing in the file LICENSE.LGPL included in the
14 ! packaging of this file. Please review the following information to
15 ! ensure the GNU Lesser General Public License version 2.1 requirements
16 ! will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
20 *===================================================================*/
22 #include <sys/types.h>
23 #include <sys/socket.h>
24 #include <netinet/in.h>
25 #include <arpa/inet.h>
27 #include <QNetworkConfigurationManager>
28 #include <QNetworkSession>
30 #include <QGraphicsView>
38 DroneVideo::DroneVideo()
40 droneHost.setAddress("192.168.1.1");
47 void DroneVideo::frameSeqUpdated()
49 emit frameSeqChanged();
52 QImage* DroneVideo::idleImage() { return m_idleImage; }
53 void DroneVideo::setIdleImage(QImage *img)
57 if(m_idleImage && image) {
59 p.drawImage(0,0,*m_idleImage);
60 update(boundingRect());
64 void DroneVideo::paint(QPainter *painter,const QStyleOptionGraphicsItem *option,
67 if(!initialized) { // We need initialize QImage here because we don't know display depth before
69 depth=painter->device()->depth();
70 qDebug() << "depth=" << depth;
73 image=new QImage(320,240, QImage::Format_RGB32);
74 image->fill(0x555555);
77 image=new QImage(320,240, QImage::Format_RGB16);
82 p.drawImage(0,0,*m_idleImage);
84 p.drawLine(0,0,image->width(),image->height());
85 p.drawLine(image->width(),0,0,image->height());
87 update(boundingRect());
88 videoThread=new VideoThread(this,droneHost,image);
89 connect(videoThread,SIGNAL(frameSeqChanged()),this,SLOT(frameSeqUpdated()));
92 painter->drawImage(boundingRect(),*image,image->rect());
95 QRectF DroneVideo::boundingRect() const
97 return QRectF(0.0,0.0,size().width(),size().height());
108 VideoThread::VideoThread(DroneVideo *parentp,QHostAddress host,QImage *_image)
110 struct ip_mreq imreq;
114 qDebug() << "videoThread::videoThread";
117 videoSock=new QUdpSocket();
118 if(!videoSock->bind(QHostAddress::Any,5555)) qDebug() << "VideoThread::VideoThread ** Cant Bind to port 5555 ***" << videoSock->errorString();
119 QList<QNetworkConfiguration> netconfs=QNetworkConfigurationManager().allConfigurations();
120 foreach (QNetworkConfiguration np,netconfs) {
121 qDebug() << "network Confifuration name " << np.name() << np.bearerName() << np.bearerTypeName();
122 QNetworkSession ns(np);
123 if(ns.interface().addressEntries().empty())
124 qDebug() << "network session " << ns.interface().humanReadableName() << "**NotConfig**";
126 qDebug() << "network session " << ns.interface().humanReadableName() << ns.interface().addressEntries().first().ip();
127 // Ubuntu may give wlan0 as "Ethernet"
128 if((np.bearerName()==QString("WLAN")) || (ns.interface().humanReadableName()==QString("wlan0")) ) {
129 my_ip=ns.interface().addressEntries().first().ip().toString();
130 qDebug() << "My IP is " << my_ip;
135 imreq.imr_multiaddr.s_addr=inet_addr("224.1.1.1");
136 imreq.imr_interface.s_addr=inet_addr(my_ip.toAscii());
137 setsockopt(videoSock->socketDescriptor(),IPPROTO_IP,IP_ADD_MEMBERSHIP,&imreq,sizeof(imreq));
138 #if QT_VERSION >= 0x040800
140 if(!videoSock->joinMulticastGroup(QHostAddress("224.1.1.1")))
141 qDebug() << "VideoThread::VideoThread can't join multicast Group 224.1.1.1" << videoSock->errorString();
151 void VideoThread::run()
153 #define ACQ_WIDTH 320
154 #define ACQ_HEIGHT 240
156 memset(&controller,0,sizeof(controller));
157 memset(&picture,0,sizeof(picture));
158 pictureWidth= image->width();
159 pictureHeight=image->height();
160 int codec_type=UVLC_CODEC;
161 qDebug() << "videoThread::run()";
162 stateTimer=new QTimer();
163 connect(stateTimer,SIGNAL(timeout()),this,SLOT(timer()));
164 connect(videoSock,SIGNAL(readyRead()),this,SLOT(videoDataReady()));
165 qDebug() << "videoThread::run() 2";
167 num_picture_decoded=0;
168 /// Picture configuration
170 picture.format = PIX_FMT_YUV420P;
171 picture.width = pictureWidth;
172 picture.height = pictureHeight;
173 picture.framerate = 30;
174 picture.y_buf = (uint8_t*)(void*)vp_os_malloc((size_t) pictureWidth*pictureHeight );
175 picture.cr_buf = (uint8_t*)vp_os_malloc( pictureWidth*pictureHeight/4 );
176 picture.cb_buf = (uint8_t*)vp_os_malloc( pictureWidth*pictureHeight/4 );
177 picture.y_line_size = pictureWidth;
178 picture.cb_line_size = pictureWidth / 2;
179 picture.cr_line_size = pictureWidth / 2;
183 qDebug() << "video_codec_open=" << video_codec_open(&controller, (codec_type_t)codec_type);
185 //stateTimer->start(1000);
186 qDebug() << "videoThread::run() initialized";
194 void VideoThread::timer()
196 // qDebug() << "thread Timer";
200 void VideoThread::sendVideoPort(QString cmd)
203 dgram=cmd.toLatin1();
204 qDebug() << "videoThread::sendCmd= " << cmd+"\n" << "to " << droneHost ;
205 videoSock->writeDatagram(dgram.data(),dgram.size(),droneHost,5555);
208 unsigned int VideoThread::getFrameSeq()
213 void VideoThread::setVideoRec(bool rec)
215 qDebug() << "VideoThread::setVideoRec" << rec;
216 QDateTime fileDate=QDateTime::currentDateTime();
217 if(!videoRec && rec) {
219 videoFileName="dronerec"+fileDate.toString("yyyyMMddhhmm");
220 qDebug() << "videoFileName=" << videoFileName;
221 emit frameSeqChanged();
224 if(!videoRec && videoFile) { // Stop recording
234 bool VideoThread::getVideoRec()
239 QString VideoThread::getVideoFileName()
241 return videoFileName;
244 void VideoThread::setVideoFileName(QString name)
249 void VideoThread::setVideoPlay(bool play)
251 if(!videoPlay && play) frameSeq=0;
256 bool VideoThread::getVideoPlay()
264 void VideoThread::videoDataReady()
267 QByteArray videoData;
271 videoData.resize(videoSock->pendingDatagramSize ());
272 l=videoSock->readDatagram(videoData.data(),videoData.size(),&host,&port);
273 // qDebug() << "videoThread::videoDataReady" <<" l=" << l << "from" << host ;
275 if(videoRec && videoFile==NULL) {
279 decodeTransform(videoData);
283 void VideoThread::decodeTransform(QByteArray &videoData)
285 controller.in_stream.bytes = (uint32_t*)videoData.data();
286 controller.in_stream.used = videoData.size();
287 controller.in_stream.size = videoData.size();
288 controller.in_stream.index = 0;
289 controller.in_stream.length = 32;
290 controller.in_stream.code = 0;
292 bool_t got_image = FALSE;
293 //qDebug() <<"VideoThread::decodeTransform" << controller.video_codec;
295 if(controller.video_codec!=NULL) video_decode_blockline( &controller, &picture, &got_image );
296 if(videoRec && !videoFile) {// Start recording
297 qDebug() << "Record Video to " << QDir::current().absolutePath() << videoFileName+".yuv" << " at " << picture.width << "x" << picture.height;
298 videoFile=new QFile(videoFileName+".yuv");
299 videoFile->open(QIODevice::WriteOnly);
300 if(videoFile->error()!=QFile::NoError) {
301 qDebug() << "Can't open Video file " << videoFileName << ".yuv" << videoFile->errorString();
307 if(!videoRec && videoFile) { // Stop recording
313 //else qDebug() << "No video controller";
314 //qDebug() <<"VideoThread::decodeTransform 2";
315 //video_decode_picture( &controller, &picture, &stream, &got_image );
318 // qDebug() <<"VideoThread::decodeTransform got image" << picture.width << picture.height << image->byteCount() << image->bytesPerLine();
319 // we got one picture
322 picture.complete = 1;
323 num_picture_decoded++;
324 if(videoFile && videoRec) {
325 videoFile->write((char*)picture.y_buf,picture.width*picture.height);
326 videoFile->write((char*)picture.cb_buf,picture.width*picture.height>>2);
327 videoFile->write((char*)picture.cr_buf,picture.width*picture.height>>2);
329 if(image->depth()<24)
330 vp_stages_YUV420P_to_RGB565(NULL,&picture,image->bits(),image->bytesPerLine());
332 vp_stages_YUV420P_to_ARGB32(NULL,&picture,image->bits(),image->bytesPerLine());
333 emit frameSeqChanged();
335 // qDebug() << "pic " << num_picture_decoded;