#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavutil/imgutils.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"
#include "libavutil/mathematics.h"
#include <png.h>
#include "SDL2/SDL.h"
// init sdl
int init_sdl(SDL_Window **window, SDL_Renderer **renderer, SDL_Texture **texture, int width, int height)
{
if (SDL_Init(SDL_INIT_VIDEO)) {
fprintf(stderr, "Could not initialize SDL - %s - %d", SDL_GetError(), __LINE__);
return -1;
}
*window = SDL_CreateWindow("SDL2 YUV", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, width, height, SDL_WINDOW_OPENGL);
if (!*window) {
fprintf(stderr, "Could not create window - %s - %d", SDL_GetError(), __LINE__);
return -1;
}
*renderer = SDL_CreateRenderer(*window, -1, 0);
if (!*renderer) {
fprintf(stderr, "Could not create renderer - %s - %d", SDL_GetError(), __LINE__);
return -1;
}
*texture = SDL_CreateTexture(*renderer, SDL_PIXELFORMAT_IYUV, SDL_TEXTUREACCESS_STREAMING, width, height);
if (!*texture) {
fprintf(stderr, "Could not create texture - %s - %d", SDL_GetError(), __LINE__);
return -1;
}
return 0;
}
int main()
// 0.230:554/main rtsp://192.168.0.39:8554/demo
{
SDL_Window *window;
SDL_Renderer *renderer;
SDL_Texture *texture;
SDL_Rect rect;
SDL_Event event;
AVFormatContext *pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, "rtsp://192.168.0.230:554/main", NULL, NULL) != 0)
{
printf("Couldn't open input stream.\r\n");
return -1;
}
// 获取视频信息
if (avformat_find_stream_info(pFormatCtx, NULL) < 0)
{
printf("Couldn't find stream information.\r\n");
return -1;
}
int videoStream = -1;
for (int i = 0; i < pFormatCtx->nb_streams; i++)
{
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO)
{
videoStream = i;
break;
}
}
if (videoStream == -1)
{
printf("Didn't find a video stream.\r\n");
return -1;
}
// 获取视频编码器
AVCodecParameters *pCodecPar = pFormatCtx->streams[videoStream]->codecpar;
AVCodec *pCodec = avcodec_find_decoder(pCodecPar->codec_id);
if (pCodec == NULL)
{
printf("Codec not found.\r\n");
return -1;
}
// 打开视频编码器
AVCodecContext *pCodecCtx = avcodec_alloc_context3(pCodec); // avcodec_alloc_context3的作用是分配一个AVCodecContext并设置默认值
if (avcodec_parameters_to_context(pCodecCtx, pCodecPar) < 0)
{
printf("Couldn't copy codec context.\r\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0)
{
printf("Couldn't open codec.\r\n");
return -1;
}
AVFrame *pFrame = av_frame_alloc();
// 给视频解码
AVPacket packet;
int frameFinished;
int i = 0;
// init_sdl
init_sdl(&window, &renderer, &texture, pCodecCtx->width, pCodecCtx->height);
while (av_read_frame(pFormatCtx, &packet) >= 0)
{
printf("av_read_frame %d\r\n", i++);
// use sdl to play video
if (packet.stream_index == videoStream)
{
avcodec_send_packet(pCodecCtx, &packet);
frameFinished = avcodec_receive_frame(pCodecCtx, pFrame);
if (frameFinished == 0)
{
SDL_UpdateYUVTexture(texture, NULL, pFrame->data[0], pFrame->linesize[0], pFrame->data[1], pFrame->linesize[1], pFrame->data[2], pFrame->linesize[2]);
SDL_RenderClear(renderer);
SDL_RenderCopy(renderer, texture, NULL, NULL);
SDL_RenderPresent(renderer);
//退出事情循环
SDL_PollEvent(&event);
switch (event.type)
{ // 退出事件循环
case SDL_QUIT:
SDL_Quit();
exit(0);
break;
default:
break;
}
}
}
}
return 0;
}
ffmpeg读取rtsp流通过sdl渲染
最新推荐文章于 2023-07-22 14:04:46 发布