#define SDL_MAIN_HANDLED
#include <SDL2/SDL.h>
#include <SDL2/SDL_main.h>
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <cstring>
extern "C" {
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/log.h>
}
bool initialize_sdl(SDL_Window*& window, SDL_Renderer*& renderer, SDL_Texture*& texture, int width, int height) {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cerr << "SDL could not initialize! SDL_Error: " << SDL_GetError() << std::endl;
return false;
}
window = SDL_CreateWindow("RTSP Stream", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_SHOWN);
if (!window) {
std::cerr << "Window could not be created! SDL_Error: " << SDL_GetError() << std::endl;
return false;
}
renderer = SDL_CreateRenderer(window, -1, 0);
if (!renderer) {
std::cerr << "Renderer could not be created! SDL_Error: " << SDL_GetError() << std::endl;
return false;
}
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_YV12, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!texture) {
std::cerr << "Texture could not be created! SDL_Error: " << SDL_GetError() << std::endl;
return false;
}
return true;
}
void cleanup_sdl(SDL_Window* window, SDL_Renderer* renderer, SDL_Texture* texture) {
if (texture) SDL_DestroyTexture(texture);
if (renderer) SDL_DestroyRenderer(renderer);
if (window) SDL_DestroyWindow(window);
SDL_Quit();
}
int main(int argc, char* argv[]) {
av_log_set_level(AV_LOG_DEBUG);
avformat_network_init();
AVFormatContext* formatCtx = avformat_alloc_context();
std::string rtspUrl = "rtsp://10.43.50.58:554/profile1";
AVDictionary* options = nullptr;
int ret = avformat_open_input(&formatCtx, rtspUrl.c_str(), nullptr, &options);
av_dict_free(&options);
if (ret < 0) {
std::cerr << "Error: Could not open input. Return code: " << ret << std::endl;
char errbuf[128];
av_strerror(ret, errbuf, sizeof(errbuf));
std::cerr << "Error: " << errbuf << std::endl;
avformat_network_deinit();
return -1;
}
if (avformat_find_stream_info(formatCtx, nullptr) < 0) {
std::cerr << "Error: Could not find stream information." << std::endl;
avformat_close_input(&formatCtx);
avformat_network_deinit();
return -1;
}
int video_stream_index = -1;
for (unsigned int i = 0; i < formatCtx->nb_streams; ++i) {
if (formatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
video_stream_index = i;
break;
}
}
if (video_stream_index == -1) {
std::cerr << "Error: No video stream found." << std::endl;
avformat_close_input(&formatCtx);
avformat_network_deinit();
return -1;
}
AVCodecParameters* codecpar = formatCtx->streams[video_stream_index]->codecpar;
const AVCodec* codec = avcodec_find_decoder(codecpar->codec_id);
if (!codec) {
std::cerr << "Error: Could not find codec." << std::endl;
avformat_close_input(&formatCtx);
avformat_network_deinit();
return -1;
}
AVCodecContext* codecCtx = avcodec_alloc_context3(codec);
if (!codecCtx) {
std::cerr << "Error: Could not allocate codec context." << std::endl;
avformat_close_input(&formatCtx);
avformat_network_deinit();
return -1;
}
if (avcodec_parameters_to_context(codecCtx, codecpar) < 0) {
std::cerr << "Error: Could not copy codec parameters." << std::endl;
avcodec_free_context(&codecCtx);
avformat_close_input(&formatCtx);
avformat_network_deinit();
return -1;
}
if (avcodec_open2(codecCtx, codec, nullptr) < 0) {
std::cerr << "Error: Could not open codec." << std::endl;
avcodec_free_context(&codecCtx);
avformat_close_input(&formatCtx);
avformat_network_deinit();
return -1;
}
AVFrame* frame = av_frame_alloc();
AVPacket* packet = av_packet_alloc();
if (!frame || !packet) {
std::cerr << "Error: Could not allocate frame or packet." << std::endl;
avcodec_free_context(&codecCtx);
avformat_close_input(&formatCtx);
avformat_network_deinit();
return -1;
}
struct SwsContext* swsCtx = sws_getContext(codecCtx->width, codecCtx->height, codecCtx->pix_fmt,
codecCtx->width, codecCtx->height, AV_PIX_FMT_YUV420P,
SWS_BILINEAR, nullptr, nullptr, nullptr);
SDL_Window* window = nullptr;
SDL_Renderer* renderer = nullptr;
SDL_Texture* texture = nullptr;
if (!initialize_sdl(window, renderer, texture, codecCtx->width, codecCtx->height)) {
std::cerr << "Error: Could not initialize SDL." << std::endl;
av_frame_free(&frame);
av_packet_free(&packet);
avcodec_free_context(&codecCtx);
avformat_close_input(&formatCtx);
avformat_network_deinit();
return -1;
}
uint8_t* yPlane = static_cast<uint8_t*>(malloc(codecCtx->width * codecCtx->height));
uint8_t* uPlane = static_cast<uint8_t*>(malloc(codecCtx->width * codecCtx->height / 4));
uint8_t* vPlane = static_cast<uint8_t*>(malloc(codecCtx->width * codecCtx->height / 4));
int yPitch = codecCtx->width;
int uvPitch = codecCtx->width / 2;
//int i = 0;
while (av_read_frame(formatCtx, packet) >= 0) {
if (packet->stream_index == video_stream_index) {
ret = avcodec_send_packet(codecCtx, packet);
if (ret < 0) {
std::cerr << "Error: Failed to send packet to decoder." << std::endl;
break;
}
//i++;
while (ret >= 0) {
ret = avcodec_receive_frame(codecCtx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
}
else if (ret < 0) {
std::cerr << "Error: Failed to receive frame from decoder." << std::endl;
break;
}
uint8_t* dest[3] = { yPlane, uPlane, vPlane };
int destLinesize[3] = { yPitch, uvPitch, uvPitch };
sws_scale(swsCtx, frame->data, frame->linesize, 0, codecCtx->height, dest, destLinesize);
SDL_UpdateYUVTexture(texture, nullptr, yPlane, yPitch, uPlane, uvPitch, vPlane, uvPitch);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, nullptr, nullptr);
SDL_RenderPresent(renderer);
}
}
av_packet_unref(packet);
SDL_Event event;
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
av_read_pause(formatCtx);
goto cleanup;
}
}
}
cleanup:
free(yPlane);
free(uPlane);
free(vPlane);
sws_freeContext(swsCtx);
av_frame_free(&frame);
av_packet_free(&packet);
avcodec_free_context(&codecCtx);
avformat_close_input(&formatCtx);
avformat_network_deinit();
cleanup_sdl(window, renderer, texture);
return 0;
}
没有合适的资源?快使用搜索试试~ 我知道了~
温馨提示
编译环境:vs2019,win 10 pro 集成技术:ffmpeg 6.1 SDL 2.0 已本地亲测可以正常播放。可以参考集成,如果是使用其他版本的ffmpeg,接口细节上可能有差异,总体流程思路一样。 可以修改代码中rtspUrl参数实现播放不同的rtsp流。代码中默认开启了日志打印,可以分析解码过程的异常,如若不需要,可以注释掉av_log_set_level(AV_LOG_DEBUG);这行代码。注释后不会再打印相关日志。 解决方案项目已经完整打包,不需要额外处理,只要编译环境没有问题就可以直接跑起来。
资源推荐
资源详情
资源评论































收起资源包目录





































































































共 265 条
- 1
- 2
- 3
资源评论


kingof201
- 粉丝: 0
上传资源 快速赚钱
我的内容管理 展开
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助


最新资源
- 土木工程制图与CAD授课计划表.doc
- 服装入库出库登记表(自动化计算)(Excel表格通用模板).xlsx
- 单片机的交通灯实习研究分析报告.doc
- 物联网时代的网络安全问题研究.docx
- 2011微机原理与接口技术复习1.doc
- 新一代人工智能引领加速发展中国智能制造.docx
- 我国电力企业财务管理信息化建设问题分析.docx
- 一管理系统中计算机应用概论.doc
- YAM-2000电力通信网监控管理系统总体方案设计书实施方案书.doc
- 计算机控制技术课程设计电阻炉温度控制系统设计.doc
- asp老师学生互标准系统研发设计方案.doc
- 标配项目管理也丰富福特翼虎详细配置曝光.doc
- 人工智能时代高职院校会计专业教学的改革.docx
- 大数据作网络时代的基层群团组织建设.docx
- 浅析事业单位档案管理信息化建设.docx
- 项目管理之范围管理管什么.docx
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈



安全验证
文档复制为VIP权益,开通VIP直接复制
