Ticket #521: qthcamera.cpp

File qthcamera.cpp, 17.9 KB (added by Denis, 15 years ago)
Line 
1#include "qthcamera.h"
2
3QThCamera::QThCamera(QObject *parent) : QThread(parent) {
4 MainForm= (QFMainForm*)parent;
5 DoStart= true;
6}
7
8QThCamera::~QThCamera() {
9 DoStart= false;
10 while (this->isRunning()) msleep(10);
11 qDebug() << "QThCamera::~QThCamera()";
12}
13
14void QThCamera::IplImageToAVFrame(IplImage* iplImage, AVFrame* avFrame, int Width, int Height, enum PixelFormat pix_fmt) {
15 int linesize[4]= {0, 0, 0, 0};
16 struct SwsContext* img_convert_ctx= sws_getContext(iplImage->width, iplImage->height, PIX_FMT_BGR24, Width, Height, pix_fmt, SWS_BICUBIC, 0, 0, 0);
17 if (img_convert_ctx!= 0) {
18 linesize[0]= 3 * iplImage->width;
19 sws_scale(img_convert_ctx, (uint8_t**)&iplImage->imageData, linesize, 0, iplImage->height, avFrame->data, avFrame->linesize);
20 sws_freeContext(img_convert_ctx);
21 }
22}
23
24typedef struct DynBuffer {
25 int pos, size, allocated_size;
26 uint8_t *buffer;
27 int io_buffer_size;
28 uint8_t io_buffer[1];
29} DynBuffer;
30
31void QThCamera::run() {
32 qDebug() << "QThCamera::run() start";
33 QString MPGFileName= "a.mp4";
34
35 CvCapture *Capture= NULL;
36 Capture= cvCreateCameraCapture(Index, Width, Height);
37 if (!Capture) qDebug() << "cvCreateCameraCapture Error!";
38 else {
39 if (ExternalFrame) cvNamedWindow("Frame", CV_WINDOW_AUTOSIZE);
40 IplImage *frame= 0;
41 CvFont font;
42 cvInitFont(&font, CV_FONT_HERSHEY_SIMPLEX, 0.5f, 0.5f);
43
44 AVOutputFormat *pOutputFormat= av_guess_format("mp4", NULL, NULL); // CODEC_ID_H264 -> mp4, rawvideo; CODEC_ID_THEORA -> ogg; CODEC_ID_MPEG4 -> mpegts, rawvideo; CODEC_ID_VP8 -> webm
45 if (!pOutputFormat) {
46 qDebug() << "Could not set output format, using MPEG.";
47 pOutputFormat= av_guess_format("mpeg", NULL, NULL);
48 }
49 if (!pOutputFormat) qDebug() << "av_guess_format Error!";
50 else {
51 AVFormatContext *pFormatCtx;
52 if (avformat_alloc_output_context2(&pFormatCtx, pOutputFormat, NULL, NULL)< 0) qDebug() << "avformat_alloc_output_context2 Error!";
53 else {
54 AVStream *pVideoStream= av_new_stream(pFormatCtx, 0);
55 if (!pVideoStream) qDebug() << "av_new_stream Error!";
56 else {
57 AVCodecContext *pCodecCtx= pVideoStream->codec;
58 pCodecCtx->codec_id= CODEC_ID_H264;
59 pCodecCtx->codec_type= AVMEDIA_TYPE_VIDEO;
60 pCodecCtx->bit_rate= 40000;
61 pCodecCtx->width= Width;
62 pCodecCtx->height= Height;
63 pCodecCtx->time_base.den= 25;
64 pCodecCtx->time_base.num= 1;
65 pCodecCtx->gop_size= 10;
66 pCodecCtx->pix_fmt= PIX_FMT_YUV420P;
67 if (pFormatCtx->oformat->flags & AVFMT_GLOBALHEADER) pCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;
68 av_dump_format(pFormatCtx, 0, NULL, 1);
69 AVCodec *pCodec= avcodec_find_encoder(pCodecCtx->codec_id);
70 if (!pCodec) qDebug() << "avcodec_find_encoder Error!";
71 else {
72 if (avcodec_open(pCodecCtx, pCodec)< 0) qDebug() << "avcodec_open Error!";
73 else {
74 QFile QFMPGFileOut;
75 QFMPGFileOut.setFileName(MPGFileName);
76 if (QFMPGFileOut.open(QIODevice::WriteOnly)) {
77
78 if (avio_open_dyn_buf(&pFormatCtx->pb)< 0) qDebug() << "avio_open Error!";
79 else {
80 if (avformat_write_header(pFormatCtx, NULL)!= 0) qDebug() << "av_write_header Error!";
81 int BYTEPIC= Width * Height * 3;
82 uint8_t *pOutBuffer= (uint8_t*)malloc(BYTEPIC); {
83 int Frames= 0;
84 QDateTime QDTStart= QDateTime::currentDateTime();
85 while (DoStart) {
86 if (!cvSetChannel(Capture, Channel)) qDebug() << "cvSetChannel Error!";
87 frame= cvQueryFrame(Capture);
88 if (frame) {
89 if (MainForm->ui->QCBAutoBrightness->isChecked()) {
90 int Brightness= BrightnessOfAPixel(frame);
91 Brightness= ((Brightness * 200 / 256) - 100) * -1;
92 IplImage *frame2= ContrastBrightness(frame, 0, Brightness); {
93 cvCopyImage(frame2, frame);
94 }{
95 cvReleaseImage(&frame2);
96 }
97 } else {
98 IplImage *frame2= ContrastBrightness(frame, MainForm->ui->QHSContrast->value(), MainForm->ui->QHSBrightness->value()); {
99 cvCopyImage(frame2, frame);
100 }{
101 cvReleaseImage(&frame2);
102 }
103 }
104 if (MainForm->ui->QCBShowDateTime->isChecked()) cvPutText(frame, QDateTime::currentDateTime().toString("dd-MM-yyyy hh:mm:ss").toAscii(), cvPoint(10, 20), &font, cvScalar(255, 255, 255));
105 if (MainForm->ui->QRBRotate90->isChecked()) {
106 IplImage *frame2= Rotate(frame, 90); {
107 cvCopyImage(frame2, frame);
108 }{
109 cvReleaseImage(&frame2);
110 }
111 } else if (MainForm->ui->QRBRotate180->isChecked()) {
112 IplImage *frame2= Rotate(frame, 180); {
113 cvCopyImage(frame2, frame);
114 }{
115 cvReleaseImage(&frame2);
116 }
117 } else if (MainForm->ui->QRBRotate270->isChecked()) {
118 IplImage *frame2= Rotate(frame, 270); {
119 cvCopyImage(frame2, frame);
120 }{
121 cvReleaseImage(&frame2);
122 }
123 }
124 if (ExternalFrame) cvShowImage("Frame", frame);
125 QImage Image(frame->width, frame->height, QImage::Format_RGB888);
126 const unsigned char *data= NULL;
127 data= (unsigned char*)(frame->imageData);
128 Image= QImage(data, frame->width, frame->height, frame->widthStep, QImage::Format_RGB888);
129 if (DoStart) emit SendNewImage(Image);
130
131 AVFrame *pAVFrame= avcodec_alloc_frame();
132 uint8_t *pBuffer= (uint8_t*)malloc(avpicture_get_size(PIX_FMT_YUV420P, Width, Height)); {
133 avpicture_fill((AVPicture*)pAVFrame, pBuffer, PIX_FMT_YUV420P, Width, Height);
134 IplImageToAVFrame(frame, pAVFrame, Width, Height, PIX_FMT_YUV420P);
135 pAVFrame->pts= Frames;
136 int OutSize= avcodec_encode_video(pCodecCtx, pOutBuffer, BYTEPIC, pAVFrame);
137 if (OutSize> 0) {
138 AVPacket Packet;
139 av_init_packet(&Packet);
140 //Packet.pts= Frames;
141 if (pCodecCtx->coded_frame->pts != AV_NOPTS_VALUE) {
142 Packet.pts= av_rescale_q(pCodecCtx->coded_frame->pts, pCodecCtx->time_base, pVideoStream->time_base);
143 }
144 if (pCodecCtx->coded_frame->key_frame) Packet.flags |= AV_PKT_FLAG_KEY;
145 Packet.stream_index= pVideoStream->index;
146 Packet.data= pOutBuffer;
147 Packet.size= OutSize;
148 if (av_interleaved_write_frame(pFormatCtx, &Packet)!= 0) qDebug() << "av_interleaved_write_frame Error!";
149
150
151 DynBuffer *d= (DynBuffer*)pFormatCtx->pb->opaque;
152 qDebug() << d->buffer << pFormatCtx->pb->buffer << pFormatCtx->pb->pos;
153 /*QByteArray QBAByteIn((const char*)d->buffer, d->pos);
154 QFMPGFileOut.write(QBAByteIn);
155 d->pos= d->size= 0;*/
156
157
158 }
159 Frames++;
160 if (Frames> pCodecCtx->time_base.den / pCodecCtx->time_base.num * 5) break;
161 }{
162 av_free(pAVFrame);
163 free(pBuffer);
164 }
165
166
167 } else qDebug() << "QThCamera::run() frame= false";
168 }
169 qDebug() << Frames / QDTStart.secsTo(QDateTime::currentDateTime());
170 }{
171 free(pOutBuffer);
172 }
173 if (av_write_trailer(pFormatCtx)!= 0) qDebug() << "av_write_trailer Error!"; // Crash with H264!!!
174 uint8_t *pDynBuffer; {
175 DynBuffer *d= (DynBuffer*)pFormatCtx->pb->opaque;
176 qDebug() << d->buffer << pFormatCtx->pb->opaque << d->allocated_size;
177 //QByteArray QBAByteIn((const char*)d->buffer, d->pos);
178 //d->pos= d->size= 0;*/
179 int pDynBufferLen= avio_close_dyn_buf(pFormatCtx->pb, &pDynBuffer);
180 qDebug() << pDynBufferLen << pDynBuffer;
181 //QByteArray QBAByteIn((const char*)pDynBuffer, pDynBufferLen);
182 //QFMPGFileOut.write(QBAByteIn);
183 }{
184 av_free(pDynBuffer);
185 }
186 }
187 QFMPGFileOut.close();
188 } else qDebug() << "QFMPGFileOut.open() Error!";
189 avcodec_close(pVideoStream->codec);
190 }
191 }
192 for (int count= 0; (unsigned)count< pFormatCtx->nb_streams; count++) {
193 av_freep(&pFormatCtx->streams[count]->codec);
194 av_freep(&pFormatCtx->streams[count]);
195 }
196 }
197 av_free(pFormatCtx);
198 }
199 }
200 cvReleaseCapture(&Capture);
201 if (ExternalFrame) cvDestroyWindow("Frame");
202 }
203 qDebug() << "QThCamera::run() stop";
204}
205
206IplImage* QThCamera::Rotate(IplImage *src, int angle) {
207 IplImage *dest= cvCloneImage(src);
208 CvPoint2D32f center;
209 center.x= dest->width / 2;
210 center.y= dest->height / 2;
211 CvMat *mapMatrix= cvCreateMat(2, 3, CV_32FC1); {
212 cv2DRotationMatrix(center, angle, 1.0, mapMatrix);
213 cvWarpAffine(src, dest, mapMatrix, CV_INTER_LINEAR + CV_WARP_FILL_OUTLIERS, cvScalarAll(0));
214 }{
215 cvReleaseMat(&mapMatrix);
216 }
217 return dest;
218}
219
220/*IplImage* QThCamera::Rotate(const IplImage *img, int angle) {
221 IplImage *newImg;
222 int newWidth, newHeight;
223 int rectX, rectY;
224 if (angle == -45 || angle == 45) {
225 newWidth= (int) ((img->width + img->height) / sqrt(2.0));
226 newHeight= (int) ((img->width + img->height) / sqrt(2.0));
227 } else if (angle == -90 || angle == 90) {
228 if (img->width > img->height) {
229 newWidth = img->width;
230 newHeight = img->width;
231 } else {
232 newWidth= img->height;
233 newHeight= img->height;
234 }
235 } else {
236 newWidth = img->width;
237 newHeight = img->height;
238 }
239 newImg= cvCreateImage(cvSize(newWidth, newHeight), img->depth, img->nChannels);
240 cvSetZero(newImg);
241 rectX = (int) ((newWidth - img->width) / 2);
242 rectY = (int) ((newHeight - img->height) / 2);
243 CvRect rect = cvRect(rectX, rectY, img->width, img->height);
244 cvSetImageROI(newImg, rect);
245 cvResize(img, newImg);
246 cvResetImageROI(newImg);
247 IplImage *rotatedImg = cvCreateImage(cvGetSize(newImg), IPL_DEPTH_8U, img -> nChannels);
248 CvPoint2D32f center;
249 int xPos, yPos;
250 xPos = (int) newWidth / 2;
251 yPos = (int) newHeight / 2;
252 CvMat *mapMatrix = cvCreateMat(2, 3, CV_32FC1);
253 center.x = xPos;
254 center.y = yPos;
255 cv2DRotationMatrix(center, angle, 1.0, mapMatrix);
256 cvWarpAffine(newImg, rotatedImg, mapMatrix);
257 return rotatedImg;
258}*/
259
260int QThCamera::BrightnessOfAPixel(IplImage *src) {
261 int Result= -1;
262 IplImage *hsv= cvCloneImage(src); {
263 cvCvtColor(src, hsv, CV_BGR2HSV);
264 int x= 0, y= 0;
265 QVector <int>QVResults;
266 if (src->nChannels== 3) {
267 IplImage *ThirthChannelImage= cvCreateImage(cvGetSize(src), 8, 1); {
268 cvSplit(hsv, NULL, NULL, ThirthChannelImage, NULL);
269 while (true) {
270 if (x< cvGetSize(src).width && y< cvGetSize(src).height) {
271 QVResults.append(cvRound(cvGetReal2D(ThirthChannelImage, x, y)));
272 x= x+ 32;
273 y= y+ 32;
274 } else break;
275 }
276 }{
277 cvReleaseImage(&ThirthChannelImage);
278 }
279 } else {
280 while (true) {
281 if (x< cvGetSize(src).width && y< cvGetSize(src).height) {
282 QVResults.append(cvRound(cvGetReal2D(hsv, x, y)));
283 x= x+ 32;
284 y= y+ 32;
285 } else break;
286 }
287 }
288 if (QVResults.count()> 0) Result= QVResults[0];
289 if (QVResults.count()> 1) {
290 for (int count= 1; count< QVResults.count(); count++) Result+= QVResults[count];
291 Result= Result / QVResults.count();
292 }
293 } {
294 cvReleaseImage(&hsv);
295 }
296 return Result;
297}
298
299IplImage* QThCamera::ContrastBrightness(IplImage *src, int Contrast, int Brightness) {
300 if(Contrast> 100) Contrast= 100;
301 if(Contrast< -100) Contrast= -100;
302 if(Brightness> 100) Brightness= 100;
303 if(Brightness< -100) Brightness= -100;
304 uchar UserData[256];
305 CvMat* MultiChannel2DMatrix;
306 IplImage *dest= cvCloneImage(src);
307 IplImage *gray= cvCreateImage(cvGetSize(src), src->depth, 1); {
308 MultiChannel2DMatrix= cvCreateMatHeader(1, 256, CV_8UC1);
309 cvSetData(MultiChannel2DMatrix, UserData, 0);
310 if(Contrast> 0) {
311 double delta= 127. * Contrast / 100;
312 double a= 255. / (255. - delta * 2);
313 double b= a * (Brightness - delta);
314 for(int count= 0; count< 256; count++) {
315 int v= cvRound(a * count + b);
316 if (v< 0) v= 0;
317 if (v> 255) v= 255;
318 UserData[count]= v;
319 }
320 } else {
321 double delta= -128. * Contrast / 100;
322 double a= (256. - delta * 2) / 255.;
323 double b= a * Brightness + delta;
324 for (int count= 0; count< 256; count++) {
325 int v= cvRound(a * count + b);
326 if (v< 0) v= 0;
327 if (v> 255) v= 255;
328 UserData[count]= v;
329 }
330 }
331 if (src->nChannels== 3) {
332 IplImage *R= cvCreateImage(cvGetSize(src), src->depth, 1);
333 IplImage *G= cvCreateImage(cvGetSize(src), src->depth, 1);
334 IplImage *B= cvCreateImage(cvGetSize(src), src->depth, 1); {
335 cvCvtPixToPlane(src, R, G, B, NULL);
336 cvLUT(R, R, MultiChannel2DMatrix);
337 cvLUT(G, G, MultiChannel2DMatrix);
338 cvLUT(B, B, MultiChannel2DMatrix);
339 cvCvtPlaneToPix(R, G, B, NULL, dest);
340 }{
341 cvReleaseImage(&R);
342 cvReleaseImage(&G);
343 cvReleaseImage(&B);
344 }
345 } else cvLUT(gray, dest, MultiChannel2DMatrix);
346 }{
347 cvReleaseImage(&gray);
348 cvReleaseMat(&MultiChannel2DMatrix);
349 }
350 return dest;
351}
352