www.pudn.com > CameraRead.zip > processImage.cpp, change:2015-12-16,size:9428b


#include <QtGui>
#include <QMessageBox>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <iostream>
#include "processImage.h"
#include "videodevice.h"

#include <unistd.h>
//luvcview -d /dev/video0 -f jpg -s 320x240
extern "C"
{
#include <stdio.h>
#include <stdlib.h>
}
/***
 * 通过调用 RTPSession 类的 SetReceiveMode() 方法可以设置下列这些接收模式:
 * RECEIVEMODE_ALL  缺省的接收模式,所有到达的 RTP 数据报都将被接受;
 * RECEIVEMODE_IGNORESOME  除了某些特定的发送者之外,所有到达的 RTP 数据报都将被接受,而被拒绝
 *      的发送者列表可以通过调用 AddToIgnoreList()、DeleteFromIgnoreList() 和 ClearIgnoreList() 方法来进
 *      行设置;
 * RECEIVEMODE_ACCEPTSOME  除了某些特定的发送者之外,所有到达的 RTP 数据报都将被拒绝,而被接受
 *   的发送者列表可以通过调用 AddToAcceptList ()、DeleteFromAcceptList 和 ClearAcceptList () 方法来进
 *   行设置。
***/

void MyRTPSession::OnRTCPCompoundPacket(RTCPCompoundPacket *pack,const RTPTime &receivetime,const RTPAddress *senderaddress)
{
    std::cout << "\nOnRTCPCompoundPacket" << std::endl;
    RTCPPacket *rtcppack;
    pack->GotoFirstPacket();
    while ((rtcppack = pack->GetNextPacket()) != 0){
        if (rtcppack->IsKnownFormat()){
            switch (rtcppack->GetPacketType()){
                case RTCPPacket::SR:{
                    RTCPSRPacket *p = (RTCPSRPacket *)rtcppack;
                    uint32_t senderssrc = p->GetSenderSSRC();
                    std::cout << "SR Info:" << std::endl;
                    std::cout << "        NTP timestamp:    " << p->GetNTPTimestamp().GetMSW() << ":" << p->GetNTPTimestamp().GetLSW() << std::endl;
                    std::cout << "        RTP timestamp:    " << p->GetRTPTimestamp() << std::endl;
                    std::cout << "        Packet count:     " <<  p->GetSenderPacketCount() << std::endl;
                    std::cout << "        Octet count:      " << p->GetSenderOctetCount() << std::endl;
                    std::cout << "        SSRC       :      " << senderssrc               << std::endl;
                    break;
                }
                case RTCPPacket::RR:{
                    std::cout << " a RR" << std::endl;
                    break;
                }
                case RTCPPacket::SDES:{
                     std::cout << " a SDES" << std::endl;
                    break;
                }
                case RTCPPacket::BYE:{
                    std::cout << " a sender Bye" << std::endl;

                    break;
                }
                case RTCPPacket::APP:{
                    std::cout << " a APP" << std::endl;
                    break;
                }
                default:
                    std::cout << " unKnown RTCP Packet" << std::endl;
            }
        }
    }
}
void MyRTPSession::OnPollThreadStep()
{
   //std::cout << "OnPollThreadStep" << std::endl;
    emit Process();
}
ProcessImage::ProcessImage(QWidget *parent):QWidget(parent)
{
    //painter = new QPainter(this);
    buffer = BufferCreate(1024*512);
    frame = new QImage(p,320,240,QImage::Format_RGB888);
    takeflag = 0;
    label = new QLabel(tr("no vedio signal"),this);
    servip = new QLabel(tr("ServIP: NULL"),this);
    setip = new QLabel(tr("SettingIP:"),this);
    comboBox = new QComboBox(this);
    thread = new MyThread(this);
    setting = new QPushButton(tr("setting"));
    save = new QPushButton(tr("take photo"));
    setting->setEnabled(false);
    ServFlag = 0;
    memset(ServIpNum,0,4);
    ServPortNum = 0;

    thread->start();
    QHBoxLayout *hLayout1 = new QHBoxLayout();
    hLayout1->addWidget(setip);
    hLayout1->addWidget(comboBox);
    QHBoxLayout *hLayout2 = new QHBoxLayout();
    hLayout2->addWidget(save);
    hLayout2->addWidget(setting);
    QVBoxLayout *vLayout = new QVBoxLayout();
    vLayout->addWidget(label);
    vLayout->addStretch();
    vLayout->addWidget(servip);
    vLayout->addLayout(hLayout1);
    vLayout->addLayout(hLayout2);
    setLayout(vLayout);
    setWindowTitle(tr("RecvPicture"));
    connect(save,SIGNAL(clicked()),this,SLOT(take_a_photo()));
    connect(comboBox,SIGNAL(activated(QString)),this,\
            SLOT(enableSettingButton(const QString &)));
    connect(setting,SIGNAL(clicked()),this,SLOT(set_servip()));
    connect(thread,SIGNAL(sendServIp(QString)),this,SLOT(addServIP(QString)));
    connect(this,SIGNAL(ServExitToThread(QString)),thread,SLOT(deleteServIp(QString)));
    connect(&session,SIGNAL(Process()),this,SLOT(update()));
    connect(&session,SIGNAL(ServExit(QString)),this,SLOT(ServExit(QString)));
}
Buffer *ProcessImage::BufferCreate(unsigned int capacity)
{
       Buffer *b = (Buffer *)malloc(sizeof(Buffer));
       b->capacity = capacity;
       b->data = (uchar *)malloc(capacity);
       b->destlength = 0;
       b->curlength = 0;
       return b;
}


ProcessImage::~ProcessImage()
{
    RTPTime delay(3.0);
    free(buffer);
    session.BYEDestroy(delay,"Time's up",9);
}
void ProcessImage::save_mjpeg()
{
     QDateTime current_date_time = QDateTime::currentDateTime();
     QString name("/home/hudong/Desktop/");
     QString current_date = current_date_time.toString("yyyy-MM-dd_hh:mm:ss");
     current_date.append(".jpg");
     name.append(current_date);
     char*  ch;
     QByteArray ba = name.toLatin1();
     ch = ba.data();
     int  fd = open(ch,O_CREAT|O_RDWR|O_TRUNC,0666);
     if(fd < 0){
         std::cout << "open failed\n" << std::endl;
         std::cout << ch << std::endl;
     }else{
         std::cout << "write\n" << ch << std::endl;
         write(fd,buffer->data,buffer->destlength);
         ::close(fd);
     }
}
void ProcessImage::take_a_photo()
{
    takeflag = 1;
}

void ProcessImage::paintEvent(QPaintEvent *)
{
    struct Packet *recvPacket;
    RTPPacket *packet;

    session.BeginDataAccess();
   
    if(session.GotoFirstSource()){
        do{
            while((packet = session.GetNextPacket()) != 0){
                recvPacket = (struct Packet *)packet->GetPayloadData();
                if(recvPacket->magic1 == 0x12345678 &&\
                        recvPacket->magic2 == 0x87654321 &&\
                        recvPacket->sum    == recvPacket->magic1 + recvPacket->magic2){
                        buffer->destlength = recvPacket->lenght;
                        buffer->curlength = 0;
                     memcpy(buffer->data+buffer->curlength,\
                            recvPacket->body,packet->GetPayloadLength() - sizeof(struct Packet));
                     buffer->curlength += packet->GetPayloadLength() - sizeof(struct Packet);
                     session.DeletePacket(packet);
                     continue;
                }
                if(buffer->destlength != 0 && \
                            buffer->curlength < buffer->destlength){
                   memcpy(buffer->data+buffer->curlength,\
                          packet->GetPayloadData(),packet->GetPayloadLength());
                   buffer->curlength += packet->GetPayloadLength();
                }
                session.DeletePacket(packet);
            }
        }while(session.GotoNextSource());
    }
    session.EndDataAccess();
    if(buffer->destlength != 0 && buffer->destlength == buffer->curlength){
        p = buffer->data;
        frame->loadFromData((uchar *)p,buffer->destlength * sizeof(char));
        label->setPixmap(QPixmap::fromImage(*frame,Qt::AutoColor));
        if(takeflag == 1){
            takeflag = 0;
            save_mjpeg();
        }
        buffer->destlength = 0;
    }
}

void ProcessImage::display_error(QString err)
{
    QMessageBox::warning(this,tr("error"), err,QMessageBox::Yes);
}

/*yuv格式转换为rgb格式*/
int ProcessImage::convert_yuv_to_rgb_buffer(unsigned char *yuv, unsigned char *rgb, unsigned int width, unsigned int height)
{
 unsigned int in, out = 0;
 unsigned int pixel_16;
 unsigned char pixel_24[3];
 unsigned int pixel32;
 int y0, u, y1, v;
 for(in = 0; in < width * height * 2; in += 4) {
  pixel_16 =
   yuv[in + 3] << 24 |
   yuv[in + 2] << 16 |
   yuv[in + 1] <<  8 |
   yuv[in + 0];
  y0 = (pixel_16 & 0x000000ff);
  u  = (pixel_16 & 0x0000ff00) >>  8;
  y1 = (pixel_16 & 0x00ff0000) >> 16;
  v  = (pixel_16 & 0xff000000) >> 24;
  pixel32 = convert_yuv_to_rgb_pixel(y0, u, v);
  pixel_24[0] = (pixel32 & 0x000000ff);
  pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
  pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
  rgb[out++] = pixel_24[0];
  rgb[out++] = pixel_24[1];
  rgb[out++] = pixel_24[2];
  pixel32 = convert_yuv_to_rgb_pixel(y1, u, v);
  pixel_24[0] = (pixel32 & 0x000000ff);
  pixel_24[1] = (pixel32 & 0x0000ff00) >> 8;
  pixel_24[2] = (pixel32 & 0x00ff0000) >> 16;
  rgb[out++] = pixel_24[0];
  rgb[out++] = pixel_24[1];
  rgb[out++] = pixel_24[2];
 }
 return 0;
}

int ProcessImage::convert_yuv_to_rgb_pixel(int y, int u, int v)
{
 unsigned int pixel32 = 0;
 unsigned char *pixel = (unsigned char *)&pixel32;
 int r, g, b;
 r = y + (1.370705 * (v-128));
 g = y - (0.698001 * (v-128)) - (0.337633 * (u-128));
 b = y + (1.732446 * (u-128));
 if(r > 255) r = 255;
 if(g > 255) g = 255;
 if(b > 255) b = 255;
 if(r < 0) r = 0;
 if(g < 0) g = 0;
 if(b < 0) b = 0;
 pixel[0] = r * 220 / 256;
 pixel[1] = g * 220 / 256;
 pixel[2] = b * 220 / 256;
 return pixel32;
}
/*yuv格式转换为rgb格式*/