ffmpeg实时编码解码部分代码
来源:互联网 发布:ios7cydia软件源 编辑:程序博客网 时间:2024/06/05 19:27
程序分为编码端和解码端,两端通过tcp socket通信,编码端一边编码一边将编码后的数据发送给解码端,解码端一边接收数据一边将解码得到的帧显示出来。
代码中的编码端编码的是实时屏幕截图。代码调用了Qt SDK。
- #ifndef MAPTHREAD_H
- #define MAPTHREAD_H
- #include <QThread>
- #include <QTcpSocket>
- #include <QTimer>
- #include <QColor>
- #include <QImage>
- #include <QPixmap>
- #include <QTime>
- #include <QDateTime>
- #include <stdio.h>
- struct AVFrame;
- struct AVPacket;
- struct AVCodec;
- struct AVCodecContext;
- class MapThread : public QThread
- {
- Q_OBJECT
- private:
- #ifdef DEBUG
- FILE* log;
- QTime* time;
- QDateTime dt;
- #endif
- AVFrame *frame;
- AVPacket* pkt;
- AVCodec *codec;
- AVCodecContext *c;
- int i, ret, x, y, got_output;
- int dest_width; //客户端指定的宽度
- int dest_height; //客户端指定的高度
- int send_width; //发送图像的宽度
- int send_height; //发送图像的高度
- int scaleby; //缩放是依据目的图像的高度还是宽度
- uchar* sent_img_buf; //buffer of the image that have been sent
- uchar* curt_img_buf; //buffer of the current image
- uchar* send_data_buf;
- uchar cmd_buf[4];
- int cmd_buf_fill;
- bool started;
- bool inited;
- int interval; //帧间时间间隔
- QTcpSocket* mapSocket;
- QTimer* timer;
- public:
- MapThread(QTcpSocket* socket, QObject *parent = 0);
- ~MapThread();
- const static int SCALE_BY_WIDTH = 1;
- const static int SCALE_BY_HEIGHT = 2;
- void setSendInterval(int i);
- signals:
- public slots:
- void sendFrame();
- void newData();
- void newCommand();
- void quit();
- protected:
- void run();
- };
- #endif // MAPTHREAD_H
- void MapThread::sendFrame()
- {
- if(!started)
- return;
- if(!inited)
- {
- avcodec_register_all();
- c= NULL;
- pkt = new AVPacket;
- i = 0;
- #ifdef DEBUG
- fprintf(log, "Encode video file %s\n", "test.mpg");
- fflush(log);
- #endif
- /* find the mpeg1 video encoder */
- codec = avcodec_find_encoder(AV_CODEC_ID_MPEG1VIDEO);
- if (codec == 0)
- {
- #ifdef DEBUG
- fprintf(log, "Codec not found\n");
- fflush(log);
- #endif
- exit(1);
- }
- c = avcodec_alloc_context3(codec);
- if (!c)
- {
- #ifdef DEBUG
- fprintf(log, "Could not allocate video codec context\n");
- fflush(log);
- #endif
- exit(1);
- }
- //c->bit_rate = 400000;
- c->width = dest_width;
- c->height = dest_height;
- c->time_base = (AVRational){1,25};
- c->gop_size = 100;
- c->max_b_frames = 0;
- c->delay = 0;
- c->pix_fmt = AV_PIX_FMT_YUV420P;
- //av_opt_set(c->priv_data, "preset", "slow", 0);
- av_opt_set(c->priv_data, "preset", "superfast", 0);
- av_opt_set(c->priv_data, "tune", "zerolatency", 0);
- int re = avcodec_open2(c, codec, NULL);
- av_opt_set(c->priv_data, "tune", "zerolatency", 0);
- if (re < 0) {
- #ifdef DEBUG
- fprintf(log, "Could not open codec:%d\n", re);
- fflush(log);
- #endif
- exit(1);
- }
- frame = av_frame_alloc();
- if (!frame) {
- #ifdef DEBUG
- fprintf(log, "Could not allocate video frame\n");
- fflush(log);
- #endif
- exit(1);
- }
- frame->format = c->pix_fmt;
- frame->width = c->width;
- frame->height = c->height;
- ret = av_image_alloc(frame->data, frame->linesize, c->width, c->height, c->pix_fmt, 32);
- if (ret < 0) {
- #ifdef DEBUG
- fprintf(log, "Could not allocate raw picture buffer\n");
- fflush(log);
- #endif
- exit(1);
- }
- inited = true;
- }
- if(mapSocket == 0)
- {
- #ifdef DEBUG
- qDebug()<<"null socket"<<endl;
- #endif
- return;
- }
- else if(mapSocket->isOpen() == false)
- {
- return;
- }
- else if(mapSocket->isWritable() == false)
- {
- return;
- }
- #ifdef DEBUG
- fprintf(log, "start cap:%d\n", QDateTime::currentDateTime().msecsTo(dt));
- #endif
- QImage image = Interface::grapScreen().toImage();
- image = image.scaled(QSize(dest_width, dest_height));
- #ifdef DEBUG
- fprintf(log, "end cap:%d\n", QDateTime::currentDateTime().msecsTo(dt));
- //fprintf(log, "cap:%d\n", time->elapsed());
- fflush(log);
- #endif
- av_init_packet(pkt);
- pkt->data = NULL; // packet data will be allocated by the encoder
- pkt->size = 1000000;
- for (int h = 0; h < c->height; h++)
- {
- for (int w = 0; w < c->width; w++)
- {
- QRgb rgb = image.pixel(w, h);
- int r = qRed(rgb);
- int g = qGreen(rgb);
- int b = qBlue(rgb);
- int dy = ((66*r + 129*g + 25*b) >> 8) + 16;
- int du = ((-38*r + -74*g + 112*b) >> 8) + 128;
- int dv = ((112*r + -94*g + -18*b) >> 8) + 128;
- uchar yy = (uchar)dy;
- uchar uu = (uchar)du;
- uchar vv = (uchar)dv;
- frame->data[0][h * frame->linesize[0] + w] = yy;
- if(h % 2 == 0 && w % 2 == 0)
- {
- frame->data[1][h/2 * (frame->linesize[1]) + w/2] = uu;
- frame->data[2][h/2 * (frame->linesize[2]) + w/2] = vv;
- }
- }
- }
- frame->pts = i;
- ret = avcodec_encode_video2(c, pkt, frame, &got_output);
- if (ret < 0)
- {
- #ifdef DEBUG
- fprintf(log, "Error encoding frame\n");
- fflush(log);
- #endif
- exit(1);
- }
- if (got_output)
- {
- #ifdef DEBUG
- fprintf(log, "start send:%d\n", QDateTime::currentDateTime().msecsTo(dt));
- #endif
- int ss = pkt->size;
- #ifdef DEBUG
- qDebug()<<"ss:"<<ss;
- fprintf(log, "size:%d\n", ss);
- #endif
- writeAndBlock(mapSocket, pkt->data, ss);
- mapSocket->flush();
- #ifdef DEBUG
- fprintf(log, "end send:%d\n", QDateTime::currentDateTime().msecsTo(dt));
- #endif
- av_free_packet(pkt);
- }
- i ++;
- }
- #ifndef MAPTHREAD_H
- #define MAPTHREAD_H
- #include <QThread>
- #include <QTcpSocket>
- #include <QDebug>
- #include <QImage>
- #include <QTime>
- #include "version.h"
- struct AVFrame;
- struct AVPacket;
- struct AVCodec;
- struct AVCodecContext;
- #define INBUF_SIZE 4096000
- #define AUDIO_INBUF_SIZE 20480
- #define AUDIO_REFILL_THRESH 4096
- #define QIMAGE_BUFFER_SIZE 12000000
- class MapThread : public QThread
- {
- Q_OBJECT
- private:
- QTime* time;
- int newF;
- uchar* img_buf;
- QTcpSocket* mapSocket;
- QString address;
- int port;
- bool socketConnected;
- int request_width;
- int request_height;
- uchar* recv_buf;
- uchar* frame_buf;
- int frame_buf_fill;
- int frame_bytes;
- uchar cmd_buf[8];
- int cmd_buf_fill;
- bool cmd_got;
- bool frame_size_setted;
- bool cmd_parsed;
- int subX;
- int subY;
- int subWidth;
- int subHeight;
- int subSize;
- int subFill;
- bool inited;
- AVFrame *frame;
- AVPacket* pkt;
- AVCodec *codec;
- AVCodecContext *c;
- int i, ret, x, y, got_output;
- //QImage* image;
- uint8_t* inbuf;
- #ifdef DEBUG
- FILE* log;
- int readlen;
- #endif
- int decode_write_frame(AVCodecContext *avctx, AVFrame *frame, AVPacket *pkt);
- public:
- int received_frame_width;
- int received_frame_height;
- QImage* image;
- MapThread(QString add, int p, int w, int h, QObject *parent = 0);
- void sendRequestSize(int width, int height);
- void getSubWindow();
- void parseCommand();
- void updateFrame();
- signals:
- void frameGot(QImage*);
- void frameSizeChanged(int, int);
- public slots:
- void newData();
- void hostConnected();
- protected:
- void run();
- };
- #endif // MAPTHREAD_H
- int MapThread::decode_write_frame(AVCodecContext *avctx, AVFrame *frame, AVPacket *pkt)
- {
- int len, got_frame;
- len = avcodec_decode_video2(avctx, frame, &got_frame, pkt);
- if (got_frame)
- {
- #ifdef DEBUG
- fprintf(tlog, "get frame:%d\n", QDateTime::currentDateTime().msecsTo(dt));
- //fprintf(tlog, "got frame:%d\n", ttime->elapsed());
- #endif
- if(image == 0)
- image = new QImage(img_buf, avctx->width, avctx->height, QImage::Format_RGB888);
- received_frame_width = avctx->width;
- received_frame_height = avctx->height;
- for(int h = 0; h < avctx->height; h++)
- {
- for(int w = 0; w < avctx->width; w ++)
- {
- int hh = h >> 1;
- int ww = w >> 1;
- int Y = frame->data[0][h * frame->linesize[0] + w];
- int U = frame->data[1][hh * (frame->linesize[1]) + ww];
- int V = frame->data[2][hh * (frame->linesize[2]) + ww];
- int C = Y - 16;
- int D = U - 128;
- int E = V - 128;
- int r = 298 * C + 409 * E + 128;
- int g = 298 * C - 100 * D - 208 * E + 128;
- int b = 298 * C + 516 * D + 128;
- r = qBound(0, r >> 8, 255);
- g = qBound(0, g >> 8, 255);
- b = qBound(0, b >> 8, 255);
- QRgb rgb = qRgb(r, g, b);
- image->setPixel(QPoint(w, h), rgb);
- }
- }
- #ifdef DEBUG
- fprintf(tlog, "emit frame:%d\n", QDateTime::currentDateTime().msecsTo(dt));
- //fprintf(tlog, "emit frame:%d\n", ttime->elapsed());
- #endif
- emit frameGot(image);
- }
- if (pkt->data) {
- pkt->size -= len;
- pkt->data += len;
- }
- return 0;
- }
- void MapThread::newData()
- {
- if(!inited)
- {
- avcodec_register_all();
- pkt = new AVPacket;
- av_init_packet(pkt);
- memset(inbuf + INBUF_SIZE, 0, FF_INPUT_BUFFER_PADDING_SIZE);
- codec = avcodec_find_decoder(AV_CODEC_ID_MPEG1VIDEO);
- if (!codec)
- {
- #ifdef DEBUG
- fprintf(log, "Codec not found\n");
- fflush(log);
- #endif
- exit(1);
- }
- c = avcodec_alloc_context3(codec);
- if (!c) {
- #ifdef DEBUG
- fprintf(log, "Could not allocate video codec context\n");
- fflush(log);
- #endif
- exit(1);
- }
- av_opt_set(c->priv_data, "preset", "superfast", 0);
- av_opt_set(c->priv_data, "tune", "zerolatency", 0);
- c->delay = 0;
- if(codec->capabilities&CODEC_CAP_TRUNCATED)
- c->flags|= CODEC_FLAG_TRUNCATED;
- if (avcodec_open2(c, codec, NULL) < 0) {
- #ifdef DEBUG
- fprintf(log, "Could not open codec\n");
- fflush(log);
- #endif
- exit(1);
- }
- frame = av_frame_alloc();
- if (!frame) {
- #ifdef DEBUG
- fprintf(log, "Could not allocate video frame\n");
- fflush(log);
- #endif
- exit(1);
- }
- inited = true;
- }
- while(true)
- {
- int nread = mapSocket->read((char*)inbuf, INBUF_SIZE);
- #ifdef DEBUG
- readlen += nread;
- fprintf(tlog, "recv time:%d\n", QDateTime::currentDateTime().msecsTo(dt));
- fprintf(tlog, "recv all:%d\n", readlen);
- fflush(tlog);
- #endif
- if(nread <= 0)
- break;
- av_init_packet(pkt);
- pkt->size = nread;
- pkt->data = inbuf;
- while (pkt->size > 0)
- {
- if (decode_write_frame(c, frame, pkt) < 0)
- exit(1);
- }
- av_free_packet(pkt);
- }
- }
http://blog.csdn.net/tobacco5648/article/details/27872431
0 0
- ffmpeg实时编码解码部分代码
- ffmpeg实时编码解码部分代码
- ffmpeg--编码解码h264
- ffmpeg入门(四) 解码部分代码整理
- ffmpeg实时解码H264数据流
- ffmpeg的音频解码部分
- ffmpeg h264实时解码用到的函数
- FFmpeg实时解码MediaRecorder视频流
- 编码解码代码
- ffmpeg解码核心代码理解
- FFMpeg官网源代码中的示例代码(编码和解码示例)(精华)
- 264编码基本概念 FFMpeg的解码流程
- ffmpeg--音频的解码和编码
- 利用 ffmpeg x264 编码解码 h264
- ffmpeg解码jpg并编码成h264
- 编译ffmpeg for x264 ,H264编码解码
- FFmpeg时间戳详解。 解码编码
- WebRTC 集成X264编码和ffmpeg解码
- Active Record 活动记录
- Android倒计时和定时器
- oracle中minus的使用
- Xcode使用 -选中工程文件时Project,target这一栏有时会被覆盖
- 解决Excel2010打开文档时只在一个窗口显示的问题
- ffmpeg实时编码解码部分代码
- android开发 switch语句编译报错“case expressions must be constant expressions”
- Java学习笔记(十六):UML类图符号以及各种关系
- Java 对象
- Linux启动流程详解
- java基础知识总结5
- 全文检索——Lucene
- 新团队新系统的奋斗践行
- 笔试题