下载项目地址:https://download.csdn.net/download/signal___/21559335

videoplayer.h

#include <QThread>
#include <QImage>

extern "C"
{
#include "libavutil/imgutils.h"
}
class VlcInstance;
class VlcMedia;
class VlcMediaPlayer;

class VideoPlayer :public QThread
{
     Q_OBJECT
public:
    explicit VideoPlayer();

~VideoPlayer();
   const static uint32_t dwLastFrameRealtime = 0;
    void startPlay();//线程开始
    //int interrupt_cb(void *ctx);

signals:
    void sig_a(int);
    void sig_b(int);
    void sig_GetOneFrame(QImage); //每获取到一帧图像 就发送此信号

protected:
    void run();

private:
    QString mFileName;

VlcInstance *_instance;
    VlcMedia *_media;
    VlcMediaPlayer *_player;
};

videoplayer.cpp

#include "videoplayer.h"
#include <stdio.h>
#include<iostream>
#include<QDebug>
#include <QDateTime>
#include <stdlib.h>

extern "C"
{
    #include "libavcodec/avcodec.h"
    #include "libavformat/avformat.h"
    #include "libavutil/pixfmt.h"
    #include "libswscale/swscale.h"
    #include "libavutil/time.h"
}
using namespace std;
VideoPlayer::VideoPlayer()
{

}
VideoPlayer::~VideoPlayer()
{

}
/*线程*/
void VideoPlayer::startPlay()
{
    this->start();

}

/*线程*/
void VideoPlayer::run()
{

AVFormatContext *pFormatCtx;
    AVCodecContext *pCodecCtx;
    AVCodec *pCodec;
    AVFrame *pFrame, *pFrameRGB;
    AVPacket *packet = NULL;
    uint8_t *out_buffer = NULL;

/*处理图片像素数据 图片像素格式转换 图片拉伸等 */
    static struct SwsContext *img_convert_ctx;

int videoStream, i, numBytes;
    int ret, got_picture;
    int b = 0;
    int a = 1;
    int num = 0;

avformat_network_init();              //初始化FFmpeg网络模块
    av_register_all();                    //初始化FFMPEG  调用了这个才能正常适用编码器和解码器(弃用函数)

//Allocate an AVFormatContext.
    pFormatCtx = avformat_alloc_context();//初始化内存

//AVDictionary是FFmpeg的键值对存储工具,FFmpeg经常使用AVDictionary设置/读取内部参数
    AVDictionary *avdic=NULL;
    char option_key[]="rtsp_transport";
    char  m_bTcp;
    //char option_value[]="udp";
    av_dict_set(&avdic,option_key,m_bTcp ? "tcp" : "udp",0);
    //av_dict_set(&avdic,option_key,option_value,0);
    //char option_key2[]="max_delay";
    char option_key2[]="stimeout";
    char option_value2[]="3000000";
    av_dict_set(&avdic, "buffer_size", "425984", 0);                 //画质优化
    av_dict_set(&avdic,option_key2,option_value2,0);
    /**
    * ultrafast,superfast, veryfast, faster, fast, medium
    * slow, slower, veryslow, placebo.
    */
   //av_dict_set(&avdic, "preset", "fast", 0); // av_opt_set(pCodecCtx->priv_data,"preset","fast",0);
   //av_dict_set(&avdic, "tune", "zerolatency", 0);

char url[]="rtsp://admin:123456@192.168.1.168:554/type=0&id=1";
    if (avformat_open_input(&pFormatCtx, url, NULL, &avdic) != 0)    //打开多媒体并获取信息
    {
        printf("can't open the file. \n");
          a = 2;
          emit sig_a(a);
            sleep(8);
            qDebug(" 111连接异常结束\n");
            thread()->terminate();
            thread()->wait();
            this->terminate();
            this->wait();

return;
    }

if(avdic != NULL)
    {
        av_dict_free(&avdic);
    }

//获取视频流信息
    if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
    {
        printf("Could't find stream infomation.\n");
        return;
    }

videoStream = -1;
    //循环查找视频中包含的流信息,直到找到视频类型的流

for (i = 0; i < pFormatCtx; i++)
    {
        if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO)//codec弃用函数
        {
            videoStream = i;
        }
    }
    qDebug("a ======%d\n",a);
    if(a == 1)
    {
        emit sig_a(a);
    }

if (videoStream == -1)
    {
        printf("Didn't find a video stream.\n");
        return;
    }

printf("-----------rtsp流输入信息----------------\n");
    av_dump_format(pFormatCtx, 0, url,0);
    printf("---------------------------------------\n");
    /*************************************************/

//查找解码器,获取指向视频流的编解码器上下文的指针
    pCodecCtx = pFormatCtx->streams[videoStream]->codec;
    //通过解封装之后从avstream结构体里获取CodecID(指定格式流)
    pCodec = avcodec_find_decoder(pCodecCtx->codec_id);

//设置编码器参数(不同参数对视频编质量或大小的影响)
    pCodecCtx->bit_rate =0;      //目标的码率,即采样的码率;显然,采样码率越大,视频大小越大  比特率
    pCodecCtx->time_base.num=1;  //下面两行:一秒钟25帧
    pCodecCtx->time_base.den=15;
    pCodecCtx->frame_number=1;   //每包一个视频帧

if (pCodec == NULL)
    {
        printf("Codec not found.\n");
        return;
    }

//打开解码器
    if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
    {
        printf("Could not open codec.\n");
        return;
    }
    pFrame = av_frame_alloc();    //创建  存储解码器信息*/
    pFrameRGB = av_frame_alloc(); //创建  存储解码器信息*/

//解码后的h264数据转换成RGB32
    img_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height,
                 pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height,
                        AV_PIX_FMT_RGB32, SWS_BICUBIC, NULL, NULL, NULL);

//图像的像素格式  图像的像素宽度  图像的像素高度(计算这个格式的图片,需要多少字节来存储)
    numBytes = avpicture_get_size(AV_PIX_FMT_RGB32, pCodecCtx->width,pCodecCtx->height);//(弃用函数)
    qDebug() << numBytes;        //需要多少字节来存储
//int flag = 0;
//if(flag == 0)
//{
     out_buffer = (uint8_t *) av_malloc(numBytes * sizeof(uint8_t));   //给存放图像数据的缓存区 开辟空间
     //瓜分上一步分配到的buffer.
     av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, out_buffer, AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height, 1);
    //根据指定的图像、提供的数组设置数据指针和线条大小参数(弃用函数相当于 av_image_fill_arrays)
     avpicture_fill((AVPicture *) pFrameRGB, out_buffer, AV_PIX_FMT_RGB32,pCodecCtx->width, pCodecCtx->height);
    /*pFrameRGB和out_buffer都是已经申请到的一段内存, 但是pFrameRGB只是申请了一段结构体内存, 结构体里面的值是空的,
     我们需要使用av_image_fill_arrays()函数来使得pFrameRGB和out_buffer关联起来, pFrameRGB里面使用的是out_buffer所指向的内存空间.*/

int y_size = pCodecCtx->width * pCodecCtx->height;
    packet = (AVPacket *) malloc(sizeof(AVPacket)); //申请一个视频帧包的大小
    av_new_packet(packet, y_size); //分配packet的数据,为packet分配一个指定大小的内存

//}
//int fa = 1;
    while (1)
    {

if (av_read_frame(pFormatCtx, packet) <  0)//每解码一个视频帧,需要先调用 av_read_frame()获得一帧视频的压缩数据,然后才能对该数据进行解码
        {
            memset(out_buffer,0,sizeof(out_buffer));
            memset(packet,0,sizeof(packet));

qDebug("mu == %d\n",++num);
           b = 1;
              emit sig_b(b);

if(num == 4)                           // read自动有十秒阻塞,每十秒记一次,四次后(40秒)关闭程序
           {
                  a = 2;
               emit sig_a(a);
                 sleep(8);
             qDebug(" 连接异常结束\n");
             thread()->terminate();
             thread()->wait();
             this->terminate();
             this->wait();
           }
           continue;
        }
     //   printf("tihs = %d\n",++fa);
          if(num != 0)
          {
              num = 0;
          }

// avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet);   //解码一帧视频数据(弃用函数)
        if (packet->stream_index == videoStream)
        {
            //送入解码器
           ret = avcodec_send_packet(pCodecCtx, packet);                    //发送数据到ffmepg,放到解码队列中
           got_picture = avcodec_receive_frame(pCodecCtx, pFrame);          //将成功的解码队列中取出1个frame
          // avcodec_decode_video2(pCodecCtx, pFrame, &got_picture,packet); //解码一帧视频数据(弃用函数)
            if (ret < 0)
            {
                memset(out_buffer,0,sizeof(out_buffer));
                memset(packet,0,sizeof(packet));
                printf("decode error.\n");
                b = 1;
                   emit sig_b(b);

continue;
            }
               b = 0;
               emit sig_b(b);

if (!got_picture)
            {
                 //颜色空间转换,最后输出到out_buffer
                sws_scale(img_convert_ctx,(uint8_t const * const *) pFrame->data,
                        pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data,
                        pFrameRGB->linesize);                              //sws_scale库可以在一个函数里面同时实现:1.图像色彩空间转换;2.分辨率缩放;3.前后图像滤波处理。

//把这个RGB数据 用QImage加载
                QImage tmpImg((uchar *)out_buffer,pCodecCtx->width,pCodecCtx->height,QImage::Format_RGB32);
              //QImage image = tmpImg.copy(); //把图像复制一份 传递给界面显示
                emit sig_GetOneFrame(image);  //发送信号
             }
         }
 //if(flag == 0)
 //{
        //释放一个包。
        av_free_packet(packet); //释放资源,否则内存会一直上升(弃用函数)
        av_packet_unref(packet);
     //   if((fa % 12) == 0)
        memset(out_buffer,0,sizeof(out_buffer));

//   qDebug("11111\n");
// }

}
    av_free(out_buffer);
    av_free(pFrameRGB);
    avcodec_close(pCodecCtx);//关闭给定的avcodeContext并释放与之关联的所有数据
    //av_dict_free(&pCodecCtx);

if(NULL != pCodecCtx){
        avcodec_free_context(&pCodecCtx);
        avdic = NULL;
    }
    if(NULL != pFormatCtx){
    avformat_close_input(&pFormatCtx);//关闭打开的输入pFormatCtx。释放它和它的所有内容并设置为空。
    pFormatCtx = NULL;
    }

}

MainWindow.h

#include <QMainWindow>
#include <QImage>
#include <QPaintEvent>
#include <QWidget>
#include <QtDebug>
#include <QTimer>
#include <qtconcurrentrun.h>
#include "videoplayer.h"
#include <QVBoxLayout>
#include <QTextCodec>
#include <QMovie>
#include <QDesktopWidget>
#include <QMessageBox>

extern "C"{
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <libavutil/avassert.h>
#include <libavutil/channel_layout.h>
#include <libavutil/opt.h>
#include <libavutil/mathematics.h>
#include <libavutil/timestamp.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libswresample/swresample.h>
#include "libavdevice/avdevice.h"
#include "libavutil/imgutils.h"
#include "libavutil/intreadwrite.h"
#include "libavutil/opt.h"
#include "libavutil/pixdesc.h"
#include "libavutil/imgutils.h"
}

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

protected:
    void paintEvent(QPaintEvent *event);
private:
    Ui::MainWindow *ui;
    VideoPlayer *mPlayer;                  //播放线程
    QTimer *timer;

QMovie *movie1;
    QImage mImage;                         //记录当前的图像
    QImage R_mImage;

QString url;

bool open_red=false;
private slots:
    void slotGetOneFrame(QImage img);
    void slotA(int a);
    void slotB(int b);
    void handleTimeout();

};

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include <QPainter>
#include <QInputDialog>
#include <QDebug>

using namespace std;
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
    QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8"));
    QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
    setWindowFlags(Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint);//全屏无边框模式
    ui->setupUi(this);
    mPlayer = new VideoPlayer;
    mPlayer->startPlay();
    ui->progressBar->setOrientation(Qt::Horizontal);
    ui->progressBar->setMinimum(0);
    ui->progressBar->setMaximum(0);

connect(mPlayer,SIGNAL(sig_a(int)),this,SLOT(slotA(int)));
    connect(mPlayer,SIGNAL(sig_b(int)),this,SLOT(slotB(int)));
    connect(mPlayer,SIGNAL(sig_GetOneFrame(QImage)),this,SLOT(slotGetOneFrame(QImage)));
}

MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::paintEvent(QPaintEvent *event)
{
   // ui->progressBar->setVisible(false);
   // ui->label->setVisible(false);
   // ui->label_2->setVisible(false);
   // ui->label_3->setVisible(false);
   // ui->label_4->setVisible(false);
    QPainter painter(this);                                //窗口的绘制

painter.setBrush(Qt::white);
    painter.drawRect(0, 0, this->width(), this->height()); //先画成白色

if (mImage.size().width() <= 0)                        //记录当前的图像
        return;
                                                           //将图像按比例缩放成和窗口一样大小
    QImage img = mImage.scaled(this->size(),Qt::KeepAspectRatio);
    int x = this->width() - img.width();
    int y = this->height() - img.height();
    x /= 2;
    y /= 2;

//ainter.drawImage(QPoint(x,y),img);                   //画出图像
     //qDebug("The image is drawn\n");

}

void MainWindow::slotGetOneFrame(QImage img)
{
    mImage = img;
    update();                                           //调用update将执行 paintEvent函数

}

void MainWindow::slotA(int a)
{
   // printf("a = %d\n",a);
    if(a == 1)
    {
        ui->progressBar->setVisible(false);
        ui->label->setVisible(false);
        ui->label_2->setVisible(false);
        ui->label_3->setVisible(false);
    }
    if(a == 2)
    {

ui->progressBar->setVisible(false);
        ui->label->setVisible(false);
        ui->label_2->setVisible(false);
        ui->label_3->setVisible(false);

ui->label_4->setVisible(true);
        QPixmap tianqi_pixmap(":/new/prefix1/11.png");
        tianqi_pixmap = tianqi_pixmap.scaled(ui->label_4->width(), ui->label_4->height(),
                                            Qt::IgnoreAspectRatio, Qt::SmoothTransformation);//设置图片大小和label的长宽一致
        ui->label_4->setPixmap(tianqi_pixmap);
        ui->label_4->show();

timer = new QTimer(this);
        timer->start(4*1000);
   connect(timer, SIGNAL(timeout()), this, SLOT(handleTimeout()));

}
}

mian.cpp

#include "mainwindow.h"
#include <QApplication>
#include <QWSServer>

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QWSServer::setCursorVisible(false);
    MainWindow w;
    w.show();

return a.exec();
}

完整代码下载:

https://download.csdn.net/download/signal___/21611285

ffmpeg打开网络摄像头编解码详细流程.相关推荐

  1. 史上最全的基于ffmpeg+sdl网络摄像头编解码播放资料(包含交叉编译过程,附带完整源码)

    原创博文,严禁私自转载,转载请注明出处!!! 近期,由于工作需要,要在开发板上跑一个摄像头,摄像头款式比较老,不支持rtsp格式,所以选择编译ffmpeg+sdl实现软解码播放摄像头,特此记录整个编译 ...

  2. FFmpeg获取网络摄像头数据解码

    对USB摄像头实时编码,在前面已经探讨过了.这次改变下思路,尝试去截取网络摄像头的H264码流,将其解码播放. 这里的测试代码,是在海康摄像头的基础上进行的. 解码的大致流程和以前的保持一致,只不过增 ...

  3. 基于FFMPEG 的跨平台视频编解码研究

    第33卷 第11期 2011年11月 武 汉 理 工 大 学 学 报 JOURNALOF WUHANUNIVERSITYOFTECHNOLOGY Vol.33 No.11 췍췍췍췍췍췍췍췍췍췍췍췍췍췍 ...

  4. 嵌入式Linux下基于FFmpeg的视频硬件编解码[图]

    转自:http://tech.c114.net/167/a674033.html 摘要: 对FFmpeg多媒体解决方案中的视频编解码流程进行研究.结合对S3C6410处理器视频硬件编解码方法的分析,阐 ...

  5. 嵌入式Linux下基于FFmpeg的视频硬件编解码

    嵌入式Linux下基于FFmpeg的视频硬件编解码[图] http://www.c114.net ( 2012/3/1 15:41 ) 摘要: 对FFmpeg多媒体解决方案中的视频编解码流程进行研究. ...

  6. 视频编解码——编码流程介绍

    为什么需要编码? 原始视频数据很庞大,比如一个150分钟,30FPS,分辨率为720✖480的彩色电影需要占用280GB.无论是物理存储还是网络传输,这都是难以负担的.所以需要编码进行压缩. 编码方式 ...

  7. 使用FFMPEG进行音视频编解码(C++) 0.简介

    FFMPEG介绍 FFMPEG是一个开源的编解码软件,读作"ef ef em peg".官方网址是:http://ffmpeg.org/.FFMPEG几乎支持所有的格式,当然了像一 ...

  8. 用 python , opencv 打开网络摄像头读取图像

    打开网络摄像头用如下代码: ########################################### import cv2 url = 'rtsp://admin:password@19 ...

  9. OpenCV之VideoCapture的使用——打开网络摄像头/图像序列

    OpenCV中的VideoCapture不仅可以打开视频.usb摄像头,还可以做很多事,例如读取流媒体文件,网络摄像头,图像序列等.OpenCV如何读取usb摄像头可以参考本人的另外一篇,地址如下:点 ...

最新文章

  1. Java学习总结:48(System类对IO的支持)
  2. poj2186(强连通分量分解)
  3. 埃洛等级分系统【转自百度百科】
  4. sonar 代码质量管理平台
  5. 如何自定义Shell登录组件
  6. 怎样在android平台上使用第三方jar包
  7. (转)快速统计二进制中1的个数
  8. 浮点数计算机的表示案例,计算机中的数据及其应用案例.docx
  9. POJ 1159 - Palindrome 优化空间LCS
  10. 职场中比拿到工资更有幸福感的是什么?
  11. MySQL的sql优化
  12. 视频教程-使用 Pandas 与 Matplotlib 分析科比职业生涯数据-Python
  13. 毕业论文概念界定要怎么写?
  14. vscode连接夜神模拟器
  15. Python安装shapely包出现WindowsError: [Error 126]解决方案
  16. MAC 笔记本的快捷键和输入法切换(搜狗)
  17. Linux中的Cat命令–如何使用Cat或Touch创建文本文件
  18. C++结构体定义及申请空间
  19. 基础知识12.25-12.26
  20. 1999~2019 年,互联网二十载野蛮生长史!

热门文章

  1. 《致我的这位朋友的一封信》 自述
  2. 4、Macbook2015 A1502 笔记本的换屏过程
  3. js匿名函数使用传参
  4. 无法加载xml文件错误
  5. SMMU架构手册之数据结构和转换流程(1)
  6. 基于stm32F4智能手环设计
  7. 近年中国互联网支付业务发展方向
  8. 从垃圾分类到边缘计算,九州云乌镇专题研讨会引发热议
  9. HyperX阿洛伊精英2——游戏机械键盘天花板级别的灯光特效
  10. (转)浏览器广告拦截规则,ublock origin自用规则!