1 Star 2 Fork 3

四月是你的谎言/HelloFFmpegPlayRtsp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
decoder.cpp 5.60 KB
一键复制 编辑 原始数据 按行查看 历史
#include "decoder.h"
#include <QDebug>
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/pixfmt.h"
#include "libswscale/swscale.h"
}
Decoder::Decoder(QObject *parent): QThread(parent)
{
}
void Decoder::run()
{
AVFormatContext *pFormatCtx = NULL;//音视频格式上下文 Format I/O context.
AVCodecContext *pCodecCtx = NULL;//音视频编码器相关信息
AVCodec *pCodec = NULL;//单种音视频编码器对应一个结构体
AVFrame *pFrame = NULL, *pFrameRGB = NULL;
AVPacket *packet = NULL;
uint8_t *out_buffer = NULL;
int s32Got_picture;
avformat_network_init();///初始化FFmpeg 网络模块
av_register_all();//注册AV模块
pFormatCtx = avformat_alloc_context();
AVDictionary *avdic = NULL;
char transport[] = "rtsp_transport";
char transport_value[] = "tcp";
char max_delay[] = "max_delay";
char max_delay_value[] = "100";
int s32Ret = av_dict_set(&avdic, transport, transport_value, 0);
if(s32Ret < 0) {
errString(s32Ret);
return ;
}
s32Ret = av_dict_set(&avdic, max_delay, max_delay_value, 0);
if(s32Ret < 0) {
errString(s32Ret);
return ;
}
// char url[] = "rtsp://192.168.0.103/sintel.264";
char *url = m_url.toLatin1().data();
//打开一个流
s32Ret = avformat_open_input(&pFormatCtx, url, NULL, &avdic);
if(s32Ret) {
errString(s32Ret);
return;
}
//获取视频流信息
s32Ret = avformat_find_stream_info(pFormatCtx, NULL);
if(s32Ret) {
errString(s32Ret);
return;
}
int videoStreamIndex = -1;
qDebug() << "stream count:" << pFormatCtx->nb_streams;
for (int i = 0; i < pFormatCtx->nb_streams; ++i) {
if(pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStreamIndex = i;
}
}
if(videoStreamIndex == -1) {
qDebug() << "Didn't find a video stream";
m_runState = -1;
return;
}
pCodecCtx = pFormatCtx->streams[videoStreamIndex]->codec;
pCodec = avcodec_find_decoder(pCodecCtx->codec_id);//根据编码器ID 来查找编码器
if(pCodec == NULL) {
errString(s32Ret);
return;
}
//这些参数都是什么意思
pCodecCtx->bit_rate = 0;
pCodecCtx->time_base.num = 1;
pCodecCtx->time_base.den = 10;
pCodecCtx->frame_number = 1;
s32Ret = avcodec_open2(pCodecCtx, pCodec, NULL);
if(s32Ret) {
errString(s32Ret);
return;
}
pFrame = av_frame_alloc();
pFrameRGB = av_frame_alloc();
SwsContext *image_convert_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt,
pCodecCtx->width, pCodecCtx->height, AV_PIX_FMT_RGB32,
SWS_BICUBIC, NULL, NULL, NULL);
if(image_convert_ctx == NULL) {
qDebug() << "image_convert_ctx failed" ;
m_runState = -1;
return;
}
//获取一张图片的大小
int numBytes = avpicture_get_size(AV_PIX_FMT_RGB32, pCodecCtx->width, pCodecCtx->height);
//申请内存
out_buffer = (uint8_t*)av_mallocz(numBytes * sizeof(uint8_t));
avpicture_fill((AVPicture *) pFrameRGB, out_buffer, AV_PIX_FMT_RGB32,
pCodecCtx->width, pCodecCtx->height);
packet = (AVPacket*)av_mallocz(sizeof(AVPacket));
s32Ret = av_new_packet(packet, pCodecCtx->width * pCodecCtx->height);
if(s32Ret) {
errString(s32Ret);
return;
}
#if 1
while (1) {
if(av_read_frame(pFormatCtx, packet) < 0) {
//< 0 on error or end of file.
break;
}
if(packet->stream_index == videoStreamIndex) {
//如果没有可以解压缩的帧为 got_picture零,否则为非零。
//Use av_frame_alloc() to get an AVFrame.
s32Ret = avcodec_decode_video2(pCodecCtx, pFrame, &s32Got_picture, packet);
if(s32Ret < 0) {
qDebug() << "decode error. \n";
m_runState = -1;
return;
}
if(s32Got_picture) {
/**
int sws_scale(struct SwsContext *c, const uint8_t *const srcSlice[],
const int srcStride[], int srcSliceY, int srcSliceH,
uint8_t *const dst[], const int dstStride[]);
***/
sws_scale(image_convert_ctx,
(uint8_t const * const * )pFrame->data,
pFrame->linesize, 0,/*要处理的切片的源图像中的位置,即切片的第一行图像中的数字(从*零开始计数)*/
pCodecCtx->height,
pFrameRGB->data,
pFrameRGB->linesize);
QImage tmpImg((uint8_t* )out_buffer, pCodecCtx->width, pCodecCtx->height,QImage::Format_RGB32);
QImage image = tmpImg.copy();//为什么要复制一份呢?
emit sendFrame(image);
}
//需要对 avcodec_decode_video2 创建的AVFrame 进行释放
}
av_free_packet(packet);
}
#endif
m_runState = 0;
av_free(out_buffer);
av_free(pFrameRGB);
out_buffer = NULL;
pFrameRGB = NULL;
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
avformat_network_deinit();
sws_freeContext(image_convert_ctx);
}
void Decoder::errString(int s32Ret)
{
char errStr[100] = {0};
av_strerror(s32Ret,errStr, sizeof(errStr));
qDebug() << errStr;
m_runState = s32Ret;
}
void Decoder::setUrl(QString &url)
{
m_url = url;
m_runState = 0;
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
C++
1
https://gitee.com/HeLiangMsg/hello-ffmpeg-play-rtsp.git
git@gitee.com:HeLiangMsg/hello-ffmpeg-play-rtsp.git
HeLiangMsg
hello-ffmpeg-play-rtsp
HelloFFmpegPlayRtsp
master

搜索帮助