ffmpeg实时编码解码部分代码

来源:互联网 发布:ios7cydia软件源 编辑:程序博客网 时间:2024/06/05 19:27

程序分为编码端和解码端,两端通过tcp  socket通信,编码端一边编码一边将编码后的数据发送给解码端,解码端一边接收数据一边将解码得到的帧显示出来。

代码中的编码端编码的是实时屏幕截图。代码调用了Qt SDK。

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #ifndef MAPTHREAD_H  
  2. #define MAPTHREAD_H  
  3.   
  4. #include <QThread>  
  5. #include <QTcpSocket>  
  6. #include <QTimer>  
  7. #include <QColor>  
  8. #include <QImage>  
  9. #include <QPixmap>  
  10. #include <QTime>  
  11. #include <QDateTime>  
  12.   
  13. #include <stdio.h>  
  14.   
  15. struct AVFrame;  
  16. struct AVPacket;  
  17. struct AVCodec;  
  18. struct AVCodecContext;  
  19.   
  20.   
  21. class MapThread : public QThread  
  22. {  
  23.     Q_OBJECT  
  24.   
  25. private:  
  26. #ifdef DEBUG  
  27.     FILE* log;  
  28.     QTime* time;  
  29.     QDateTime dt;  
  30. #endif  
  31.   
  32.     AVFrame *frame;  
  33.     AVPacket* pkt;  
  34.     AVCodec *codec;  
  35.     AVCodecContext *c;  
  36.     int i, ret, x, y, got_output;  
  37.   
  38.     int dest_width;           //客户端指定的宽度  
  39.     int dest_height;          //客户端指定的高度  
  40.     int send_width;           //发送图像的宽度  
  41.     int send_height;          //发送图像的高度  
  42.     int scaleby;              //缩放是依据目的图像的高度还是宽度  
  43.   
  44.     uchar* sent_img_buf;   //buffer of the image that have been sent  
  45.     uchar* curt_img_buf;   //buffer of the current image  
  46.     uchar* send_data_buf;  
  47.     uchar cmd_buf[4];  
  48.     int   cmd_buf_fill;  
  49.   
  50.     bool started;  
  51.     bool inited;  
  52.   
  53.     int          interval;         //帧间时间间隔  
  54.     QTcpSocket*  mapSocket;  
  55.     QTimer* timer;  
  56.   
  57. public:  
  58.     MapThread(QTcpSocket* socket, QObject *parent = 0);  
  59.     ~MapThread();  
  60.   
  61.     const static int SCALE_BY_WIDTH  = 1;  
  62.     const static int SCALE_BY_HEIGHT = 2;  
  63.   
  64.     void setSendInterval(int i);  
  65.       
  66. signals:  
  67.       
  68. public slots:  
  69.     void sendFrame();  
  70.     void newData();  
  71.     void newCommand();  
  72.     void quit();  
  73.   
  74. protected:  
  75.     void run();  
  76.       
  77. };  
  78.   
  79. #endif // MAPTHREAD_H  


[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void MapThread::sendFrame()  
  2. {  
  3.     if(!started)  
  4.         return;  
  5.   
  6.     if(!inited)  
  7.     {  
  8.         avcodec_register_all();  
  9.   
  10.         c= NULL;  
  11.         pkt = new AVPacket;  
  12.         i = 0;  
  13.   
  14. #ifdef DEBUG  
  15.         fprintf(log, "Encode video file %s\n""test.mpg");  
  16.         fflush(log);  
  17. #endif  
  18.         /* find the mpeg1 video encoder */  
  19.         codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO);  
  20.   
  21.         if (codec == 0)  
  22.         {  
  23. #ifdef DEBUG  
  24.             fprintf(log, "Codec not found\n");  
  25.             fflush(log);  
  26. #endif  
  27.             exit(1);  
  28.         }  
  29.   
  30.         c = avcodec_alloc_context3(codec);  
  31.         if (!c)  
  32.         {  
  33. #ifdef DEBUG  
  34.             fprintf(log, "Could not allocate video codec context\n");  
  35.             fflush(log);  
  36. #endif  
  37.             exit(1);  
  38.         }  
  39.         //c->bit_rate = 400000;  
  40.         c->width = dest_width;  
  41.         c->height = dest_height;  
  42.   
  43.         c->time_base = (AVRational){1,25};  
  44.         c->gop_size = 100;  
  45.         c->max_b_frames = 0;  
  46.         c->delay = 0;  
  47.         c->pix_fmt = AV_PIX_FMT_YUV420P;  
  48.   
  49.         //av_opt_set(c->priv_data, "preset", "slow", 0);  
  50.   
  51.         av_opt_set(c->priv_data, "preset""superfast", 0);  
  52.         av_opt_set(c->priv_data, "tune""zerolatency", 0);  
  53.   
  54.         int re = avcodec_open2(c, codec, NULL);  
  55.         av_opt_set(c->priv_data, "tune""zerolatency", 0);  
  56.         if (re < 0) {  
  57. #ifdef DEBUG  
  58.             fprintf(log, "Could not open codec:%d\n", re);  
  59.             fflush(log);  
  60. #endif  
  61.             exit(1);  
  62.         }  
  63.   
  64.         frame = av_frame_alloc();  
  65.         if (!frame) {  
  66. #ifdef DEBUG  
  67.             fprintf(log, "Could not allocate video frame\n");  
  68.             fflush(log);  
  69. #endif  
  70.             exit(1);  
  71.         }  
  72.         frame->format = c->pix_fmt;  
  73.         frame->width  = c->width;  
  74.         frame->height = c->height;  
  75.   
  76.         ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32);  
  77.         if (ret < 0) {  
  78. #ifdef DEBUG  
  79.             fprintf(log, "Could not allocate raw picture buffer\n");  
  80.             fflush(log);  
  81. #endif  
  82.             exit(1);  
  83.         }  
  84.         inited = true;  
  85.     }  
  86.   
  87.   
  88.     if(mapSocket == 0)  
  89.     {  
  90. #ifdef DEBUG  
  91.         qDebug()<<"null socket"<<endl;  
  92. #endif  
  93.         return;  
  94.     }  
  95.     else if(mapSocket->isOpen() == false)  
  96.     {  
  97.         return;  
  98.     }  
  99.     else if(mapSocket->isWritable() == false)  
  100.     {  
  101.         return;  
  102.     }  
  103. #ifdef DEBUG  
  104.     fprintf(log, "start cap:%d\n", QDateTime::currentDateTime().msecsTo(dt));  
  105. #endif  
  106.     QImage image = Interface::grapScreen().toImage();  
  107.     image = image.scaled(QSize(dest_width, dest_height));  
  108.   
  109. #ifdef DEBUG  
  110.     fprintf(log, "end cap:%d\n", QDateTime::currentDateTime().msecsTo(dt));  
  111.     //fprintf(log, "cap:%d\n", time->elapsed());  
  112.     fflush(log);  
  113. #endif  
  114.   
  115.   
  116.     av_init_packet(pkt);  
  117.     pkt->data = NULL;    // packet data will be allocated by the encoder  
  118.     pkt->size = 1000000;  
  119.   
  120.     for (int h = 0; h < c->height; h++)  
  121.     {  
  122.         for (int w = 0; w < c->width; w++)  
  123.         {  
  124.             QRgb rgb = image.pixel(w, h);  
  125.   
  126.             int r = qRed(rgb);  
  127.             int g = qGreen(rgb);  
  128.             int b = qBlue(rgb);  
  129.   
  130.             int dy = ((66*r + 129*g + 25*b) >> 8) + 16;  
  131.             int du = ((-38*r + -74*g + 112*b) >> 8) + 128;  
  132.             int dv = ((112*r + -94*g + -18*b) >> 8) + 128;  
  133.   
  134.             uchar yy = (uchar)dy;  
  135.             uchar uu = (uchar)du;  
  136.             uchar vv = (uchar)dv;  
  137.   
  138.             frame->data[0][h * frame->linesize[0] + w] = yy;  
  139.   
  140.             if(h % 2 == 0 && w % 2 == 0)  
  141.             {  
  142.                 frame->data[1][h/2 * (frame->linesize[1]) + w/2] = uu;  
  143.                 frame->data[2][h/2 * (frame->linesize[2]) + w/2] = vv;  
  144.             }  
  145.   
  146.         }  
  147.     }  
  148.   
  149.     frame->pts = i;  
  150.   
  151.     ret = avcodec_encode_video2(c, pkt, frame, &got_output);  
  152.   
  153.     if (ret < 0)  
  154.     {  
  155. #ifdef DEBUG  
  156.         fprintf(log, "Error encoding frame\n");  
  157.         fflush(log);  
  158. #endif  
  159.         exit(1);  
  160.     }  
  161.   
  162.     if (got_output)  
  163.     {  
  164. #ifdef DEBUG  
  165.         fprintf(log, "start send:%d\n", QDateTime::currentDateTime().msecsTo(dt));  
  166. #endif  
  167.         int ss = pkt->size;  
  168. #ifdef DEBUG  
  169.         qDebug()<<"ss:"<<ss;  
  170.         fprintf(log, "size:%d\n", ss);  
  171. #endif  
  172.         writeAndBlock(mapSocket, pkt->data, ss);  
  173.         mapSocket->flush();  
  174. #ifdef DEBUG  
  175.         fprintf(log, "end send:%d\n", QDateTime::currentDateTime().msecsTo(dt));  
  176. #endif  
  177.   
  178.         av_free_packet(pkt);  
  179.     }  
  180.   
  181.     i ++;  
  182. }  


解码端:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. #ifndef MAPTHREAD_H  
  2. #define MAPTHREAD_H  
  3.   
  4. #include <QThread>  
  5. #include <QTcpSocket>  
  6. #include <QDebug>  
  7. #include <QImage>  
  8. #include <QTime>  
  9.   
  10. #include "version.h"  
  11. struct AVFrame;  
  12. struct AVPacket;  
  13. struct AVCodec;  
  14. struct AVCodecContext;  
  15.   
  16. #define INBUF_SIZE 4096000  
  17. #define AUDIO_INBUF_SIZE 20480  
  18. #define AUDIO_REFILL_THRESH 4096  
  19. #define QIMAGE_BUFFER_SIZE 12000000  
  20.   
  21. class MapThread : public QThread  
  22. {  
  23.     Q_OBJECT  
  24.   
  25. private:  
  26.     QTime* time;  
  27.     int newF;  
  28.   
  29.     uchar* img_buf;  
  30.     QTcpSocket* mapSocket;  
  31.     QString     address;  
  32.     int         port;  
  33.     bool socketConnected;  
  34.   
  35.     int request_width;  
  36.     int request_height;  
  37.   
  38.     uchar* recv_buf;  
  39.     uchar* frame_buf;  
  40.     int    frame_buf_fill;  
  41.     int    frame_bytes;  
  42.     uchar  cmd_buf[8];  
  43.     int    cmd_buf_fill;  
  44.   
  45.     bool cmd_got;  
  46.     bool frame_size_setted;  
  47.   
  48.     bool cmd_parsed;  
  49.     int subX;  
  50.     int subY;  
  51.     int subWidth;  
  52.     int subHeight;  
  53.     int subSize;  
  54.     int subFill;  
  55.   
  56.     bool inited;  
  57.     AVFrame *frame;  
  58.     AVPacket* pkt;  
  59.     AVCodec *codec;  
  60.     AVCodecContext *c;  
  61.     int i, ret, x, y, got_output;  
  62.   
  63.     //QImage* image;  
  64.   
  65.     uint8_t* inbuf;  
  66. #ifdef DEBUG  
  67.     FILE* log;  
  68.     int readlen;  
  69. #endif  
  70.   
  71.     int decode_write_frame(AVCodecContext *avctx, AVFrame *frame, AVPacket *pkt);  
  72.   
  73. public:  
  74.     int received_frame_width;  
  75.     int received_frame_height;  
  76.     QImage*  image;  
  77.   
  78.     MapThread(QString add, int p, int w, int h, QObject *parent = 0);  
  79.     void sendRequestSize(int width, int height);  
  80.     void getSubWindow();  
  81.     void parseCommand();  
  82.     void updateFrame();  
  83.       
  84. signals:  
  85.     void frameGot(QImage*);  
  86.     void frameSizeChanged(intint);  
  87.       
  88. public slots:  
  89.     void newData();  
  90.     void hostConnected();  
  91.   
  92. protected:  
  93.     void run();  
  94.       
  95. };  
  96.   
  97. #endif // MAPTHREAD_H  


[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int MapThread::decode_write_frame(AVCodecContext *avctx, AVFrame *frame, AVPacket *pkt)  
  2. {  
  3.     int len, got_frame;  
  4.     len = avcodec_decode_video2(avctx, frame, &got_frame, pkt);  
  5.   
  6.     if (got_frame)  
  7.     {  
  8. #ifdef DEBUG  
  9.         fprintf(tlog, "get frame:%d\n", QDateTime::currentDateTime().msecsTo(dt));  
  10.         //fprintf(tlog, "got frame:%d\n", ttime->elapsed());  
  11. #endif  
  12.   
  13.         if(image == 0)  
  14.             image = new QImage(img_buf, avctx->width, avctx->height, QImage::Format_RGB888);  
  15.   
  16.         received_frame_width = avctx->width;  
  17.         received_frame_height = avctx->height;  
  18.   
  19.         for(int h = 0; h < avctx->height; h++)  
  20.         {  
  21.             for(int w = 0; w < avctx->width; w ++)  
  22.             {  
  23.                 int hh = h >> 1;  
  24.                 int ww = w >> 1;  
  25.                 int Y = frame->data[0][h * frame->linesize[0] + w];  
  26.                 int U = frame->data[1][hh * (frame->linesize[1]) + ww];  
  27.                 int V = frame->data[2][hh * (frame->linesize[2]) + ww];  
  28.   
  29.                 int C = Y - 16;  
  30.                 int D = U - 128;  
  31.                 int E = V - 128;  
  32.   
  33.                 int r = 298 * C           + 409 * E + 128;  
  34.                 int g = 298 * C - 100 * D - 208 * E + 128;  
  35.                 int b = 298 * C + 516 * D           + 128;  
  36.   
  37.                 r = qBound(0, r >> 8, 255);  
  38.                 g = qBound(0, g >> 8, 255);  
  39.                 b = qBound(0, b >> 8, 255);  
  40.   
  41.                 QRgb rgb = qRgb(r, g, b);  
  42.                 image->setPixel(QPoint(w, h), rgb);  
  43.             }  
  44.         }  
  45. #ifdef DEBUG  
  46.         fprintf(tlog, "emit frame:%d\n", QDateTime::currentDateTime().msecsTo(dt));  
  47.         //fprintf(tlog, "emit frame:%d\n", ttime->elapsed());  
  48. #endif  
  49.         emit frameGot(image);  
  50.     }  
  51.     if (pkt->data) {  
  52.         pkt->size -= len;  
  53.         pkt->data += len;  
  54.     }  
  55.   
  56.     return 0;  
  57. }  


[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. void MapThread::newData()  
  2. {  
  3.     if(!inited)  
  4.     {  
  5.         avcodec_register_all();  
  6.   
  7.         pkt = new AVPacket;  
  8.         av_init_packet(pkt);  
  9.   
  10.         memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);  
  11.   
  12.         codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);  
  13.         if (!codec)  
  14.         {  
  15. #ifdef DEBUG  
  16.             fprintf(log, "Codec not found\n");  
  17.             fflush(log);  
  18. #endif  
  19.             exit(1);  
  20.         }  
  21.         c = avcodec_alloc_context3(codec);  
  22.   
  23.         if (!c) {  
  24. #ifdef DEBUG  
  25.             fprintf(log, "Could not allocate video codec context\n");  
  26.             fflush(log);  
  27. #endif  
  28.             exit(1);  
  29.         }  
  30.   
  31.         av_opt_set(c->priv_data, "preset""superfast", 0);  
  32.         av_opt_set(c->priv_data, "tune""zerolatency", 0);  
  33.   
  34.         c->delay = 0;  
  35.   
  36.         if(codec->capabilities&CODEC_CAP_TRUNCATED)  
  37.             c->flags|= CODEC_FLAG_TRUNCATED;  
  38.         if (avcodec_open2(c, codec, NULL) < 0) {  
  39. #ifdef DEBUG  
  40.             fprintf(log, "Could not open codec\n");  
  41.             fflush(log);  
  42. #endif  
  43.             exit(1);  
  44.         }  
  45.   
  46.         frame = av_frame_alloc();  
  47.         if (!frame) {  
  48. #ifdef DEBUG  
  49.             fprintf(log, "Could not allocate video frame\n");  
  50.             fflush(log);  
  51. #endif  
  52.             exit(1);  
  53.         }  
  54.   
  55.         inited = true;  
  56.     }  
  57.     while(true)  
  58.     {  
  59.         int nread = mapSocket->read((char*)inbuf, INBUF_SIZE);  
  60. #ifdef DEBUG  
  61.         readlen += nread;  
  62.         fprintf(tlog, "recv time:%d\n", QDateTime::currentDateTime().msecsTo(dt));  
  63.         fprintf(tlog, "recv all:%d\n", readlen);  
  64.         fflush(tlog);  
  65. #endif  
  66.   
  67.         if(nread <= 0)  
  68.             break;  
  69.   
  70.         av_init_packet(pkt);  
  71.         pkt->size = nread;  
  72.         pkt->data = inbuf;  
  73.         while (pkt->size > 0)  
  74.         {  
  75.             if (decode_write_frame(c, frame, pkt) < 0)  
  76.                 exit(1);  
  77.         }  
  78.         av_free_packet(pkt);  
  79.     }  
  80. }  



http://blog.csdn.net/tobacco5648/article/details/27872431

0 0
原创粉丝点击