Video record function added
[mardrone] / mardrone / dronelib / video.cpp
1 /*==================================================================
2   !
3   !  mardrone application AR-Drone for MeeGo
4
5   ! Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
6   ! All rights reserved.
7   !
8   !  Author:Kate Alhola  kate.alhola@nokia.com
9   !
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.
17   !
18   !
19   !
20   *===================================================================*/
21 #include "video.h"
22 #include <QGraphicsView>
23 #include <QDateTime>
24 #include <QDir>
25
26 #ifdef QT_IOS
27 #define NO_VIDEO
28 #endif
29
30 DroneVideo::DroneVideo()
31 {
32      droneHost.setAddress("192.168.1.1");
33      initialized=false;
34      m_idleImage=NULL;
35      videoThread=NULL;
36 }
37
38
39 void DroneVideo::frameSeqUpdated()
40 {
41     emit frameSeqChanged();
42 }
43
44 QImage* DroneVideo::idleImage() { return m_idleImage; }
45 void DroneVideo::setIdleImage(QImage *img)
46 {
47     m_idleImage=img;
48
49     if(m_idleImage && image) {
50         QPainter p(image);
51         p.drawImage(0,0,*m_idleImage);
52         update(boundingRect());
53     }
54 };
55
56 void DroneVideo::paint(QPainter *painter,const QStyleOptionGraphicsItem *option,
57                         QWidget *widget)
58  {
59     if(!initialized) { // We need initialize QImage here because we don't know display depth before
60
61         depth=painter->device()->depth();
62         qDebug() << "depth=" << depth;
63
64         if(depth>=24) {
65             image=new QImage(320,240, QImage::Format_RGB32);
66              image->fill(0x555555);
67         }
68         else {
69             image=new QImage(320,240, QImage::Format_RGB16);
70             image->fill(0x5555);
71         }
72         QPainter p(image);
73         if(m_idleImage) {
74             p.drawImage(0,0,*m_idleImage);
75         } else {
76           p.drawLine(0,0,image->width(),image->height());
77           p.drawLine(image->width(),0,0,image->height());
78         }
79         update(boundingRect());
80         videoThread=new VideoThread(this,droneHost,image);
81         connect(videoThread,SIGNAL(frameSeqChanged()),this,SLOT(frameSeqUpdated()));
82         initialized=true;
83     } else
84     painter->drawImage(boundingRect(),*image,image->rect());
85  };
86
87 QRectF DroneVideo::boundingRect() const
88 {
89     return QRectF(0.0,0.0,size().width(),size().height());
90 }
91
92
93 /*
94
95   VideoThread
96
97   */
98
99
100 VideoThread::VideoThread(DroneVideo *parentp,QHostAddress host,QImage *_image)
101 {
102     image=_image;
103     qDebug() << "videoThread::videoThread";
104     stopped=false;
105     parent=parentp;
106     videoSock=new QUdpSocket();
107     videoSock->bind(QHostAddress::Any,5555);
108     droneHost=host;
109     videoRec=FALSE;
110     videoFile=NULL;
111     start();
112
113 };
114
115
116 void VideoThread::run()
117 {
118 #define ACQ_WIDTH     320
119 #define ACQ_HEIGHT    240
120 #undef memset
121     memset(&controller,0,sizeof(controller));
122     memset(&picture,0,sizeof(picture));
123     pictureWidth= image->width();
124     pictureHeight=image->height();
125     int codec_type=UVLC_CODEC;
126     qDebug() << "videoThread::run()";
127     stateTimer=new QTimer();
128     connect(stateTimer,SIGNAL(timeout()),this,SLOT(timer()));
129     connect(videoSock,SIGNAL(readyRead()),this,SLOT(videoDataReady()));
130     qDebug() << "videoThread::run() 2";
131     luma_only=FALSE;
132     num_picture_decoded=0;
133     /// Picture configuration
134 #ifndef NO_VIDEO
135     picture.format        = PIX_FMT_YUV420P;
136     picture.width         = pictureWidth;
137     picture.height        = pictureHeight;
138     picture.framerate     = 30;
139     picture.y_buf         = (uint8_t*)(void*)vp_os_malloc((size_t) pictureWidth*pictureHeight );
140     picture.cr_buf        = (uint8_t*)vp_os_malloc( pictureWidth*pictureHeight/4 );
141     picture.cb_buf        = (uint8_t*)vp_os_malloc( pictureWidth*pictureHeight/4 );
142     picture.y_line_size   = pictureWidth;
143     picture.cb_line_size  = pictureWidth / 2;
144     picture.cr_line_size  = pictureWidth / 2;
145     picture.y_pad         = 0;
146     picture.c_pad         = 0;
147
148     qDebug() << "video_codec_open=" << video_codec_open(&controller, (codec_type_t)codec_type);
149 #endif
150     //stateTimer->start(1000);
151     qDebug() << "videoThread::run() initialized";
152     sendVideoPort("AT");
153     while(!stopped) {
154         exec();
155     }
156
157 }
158
159 void VideoThread::timer()
160 {
161   //  qDebug() << "thread Timer";
162
163 }
164
165 void VideoThread::sendVideoPort(QString cmd)
166 {
167     QByteArray dgram;
168     dgram=cmd.toLatin1();
169     qDebug() << "videoThread::sendCmd= " << cmd+"\n" << "to " << droneHost ;
170     videoSock->writeDatagram(dgram.data(),dgram.size(),droneHost,5555);
171 }
172
173 unsigned int VideoThread::getFrameSeq()
174 {
175     return frameSeq;
176 }
177
178 void VideoThread::setVideoRec(bool rec)
179 {
180     qDebug() << "VideoThread::setVideoRec" <<  rec;
181     QDateTime fileDate=QDateTime::currentDateTime();
182     if(!videoRec && rec) {
183         frameSeq=0;
184         videoFileName="dronerec"+fileDate.toString("yyyyMMddhhmm");
185         qDebug() << "videoFileName=" <<  videoFileName;
186         emit frameSeqChanged();
187     }
188     videoRec=rec;
189     if(!videoRec && videoFile) { // Stop recording
190         videoFile->close();
191         videoFile->~QFile();
192         videoFile=NULL;
193         videoFileName="";
194     }
195
196
197 }
198
199 bool VideoThread::getVideoRec()
200 {
201     return videoRec;
202 }
203
204 QString VideoThread::getVideoFileName()
205 {
206     return videoFileName;
207 }
208
209 void VideoThread::setVideoFileName(QString name)
210 {
211     videoFileName=name;
212 }
213
214 void VideoThread::setVideoPlay(bool play)
215 {
216     if(!videoPlay && play) frameSeq=0;
217         videoPlay=true;
218         videoRec=false;
219 }
220
221 bool VideoThread::getVideoPlay()
222 {
223     return videoPlay;
224 }
225
226
227
228
229 void VideoThread::videoDataReady()
230 {
231    qint64 l;
232    QByteArray videoData;
233
234    QHostAddress host;
235    quint16 port;
236    videoData.resize(videoSock->pendingDatagramSize ());
237    l=videoSock->readDatagram(videoData.data(),videoData.size(),&host,&port);
238 //   qDebug() << "videoThread::videoDataReady" <<" l=" << l << "from"  << host ;
239
240    if(videoRec && videoFile==NULL) {
241        // Open Video File
242    }
243
244    decodeTransform(videoData);
245
246 }
247
248 void VideoThread::decodeTransform(QByteArray &videoData)
249 {
250     controller.in_stream.bytes   = (uint32_t*)videoData.data();
251     controller.in_stream.used    = videoData.size();
252     controller.in_stream.size    = videoData.size();
253     controller.in_stream.index   = 0;
254     controller.in_stream.length  = 32;
255     controller.in_stream.code    = 0;
256
257     bool_t got_image = FALSE;
258     //qDebug() <<"VideoThread::decodeTransform" << controller.video_codec;
259 #ifndef NO_VIDEO
260     if(controller.video_codec!=NULL)  video_decode_blockline( &controller, &picture, &got_image );
261     if(videoRec && !videoFile) {// Start recording
262         qDebug() << "Record Video to " << QDir::current().absolutePath()  << videoFileName+".yuv" << " at " << picture.width << "x" << picture.height;
263         videoFile=new QFile(videoFileName+".yuv");
264         videoFile->open(QIODevice::WriteOnly);
265         if(videoFile->error()!=QFile::NoError) {
266             qDebug() << "Can't open Video file " << videoFileName << ".yuv" << videoFile->errorString();
267             videoFile->~QFile();
268             videoFile=NULL;
269             videoRec=false;
270         }
271     }
272      if(!videoRec && videoFile) { // Stop recording
273          videoFile->close();
274          videoFile->~QFile();
275          videoFile=NULL;
276          videoFileName="";
277      }
278     //else qDebug() << "No video controller";
279     //qDebug() <<"VideoThread::decodeTransform 2";
280     //video_decode_picture( &controller, &picture, &stream, &got_image );
281     if( got_image )
282         {
283           //  qDebug() <<"VideoThread::decodeTransform got image" << picture.width << picture.height << image->byteCount() << image->bytesPerLine();
284           // we got one picture
285           // out->size = 1;
286           frameSeq++;
287           picture.complete     = 1;
288           num_picture_decoded++;
289           if(videoFile && videoRec) {
290             videoFile->write((char*)picture.y_buf,picture.width*picture.height);
291             videoFile->write((char*)picture.cb_buf,picture.width*picture.height>>2);
292             videoFile->write((char*)picture.cr_buf,picture.width*picture.height>>2);
293           };
294           if(image->depth()<24)
295             vp_stages_YUV420P_to_RGB565(NULL,&picture,image->bits(),image->bytesPerLine());
296           else
297             vp_stages_YUV420P_to_ARGB32(NULL,&picture,image->bits(),image->bytesPerLine());
298           emit frameSeqChanged();
299
300        //   qDebug() << "pic " << num_picture_decoded;
301         }
302 #endif
303
304 };
305
306