FFmpeg拉流H264视频流rstp推流C语言程序
时间: 2024-01-14 19:18:47 浏览: 197
你可以使用FFmpeg来拉取H264视频流并在浏览器中播放。以下是一些步骤和方法:
1.使用FFmpeg的avformat_open_input()函数打开视频流。
2.使用avformat_find_stream_info()函数查找视频流的信息。
3.使用avcodec_find_decoder()函数查找解码器。
4.使用avcodec_open2()函数打开解码器。
5.使用av_read_frame()函数读取视频帧。
6.使用avcodec_decode_video2()函数解码视频帧。
7.使用sws_scale()函数将解码后的视频帧转换为RGB格式。
8.使用SDL库或其他库将RGB格式的视频帧显示在屏幕上。
以下是一个简单的C语言程序,可以使用FFmpeg拉取H264视频流并将其显示在屏幕上:
<<引用:>>
gcc VedioToH264_demo.c -o ffmpegtest -I /home/xy/ffmpeg/ffmpeg-4.0.2/out/include/ -L /home/xy/ffmpeg/ffmpeg-4.0.2/out/lib/ -lavformat -lavcodec -lavutil -lswresample -lm -pthread -lrt -ldl -lz -lX11 -lvdpau
<<代码>>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#define SDL_AUDIO_BUFFER_SIZE 1024
#define MAX_AUDIO_FRAME_SIZE 192000
int quit = 0;
void quit_signal(int signo)
{
quit = 1;
}
int main(int argc, char *argv[])
{
AVFormatContext *pFormatCtx = NULL;
int i, videoStream;
AVCodecContext *pCodecCtxOrig = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL;
AVPacket packet;
int frameFinished;
struct SwsContext *sws_ctx = NULL;
SDL_Surface *screen = NULL;
SDL_Overlay *bmp = NULL;
SDL_Rect rect;
SDL_Event event;
SDL_Thread *video_tid = NULL;
int videoWidth, videoHeight;
Uint32 pixformat;
char *filename = "rtsp://192.168.1.100:554/av0_0";
int ret;
signal(SIGINT, quit_signal);
signal(SIGTERM, quit_signal);
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
fprintf(stderr, "Cannot open input file\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
fprintf(stderr, "Cannot find stream information\n");
return -1;
}
videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
}
if (videoStream == -1) {
fprintf(stderr, "Cannot find a video stream\n");
return -1;
}
pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id);
if (pCodec == NULL) {
fprintf(stderr, "Unsupported codec\n");
return -1;
}
pCodecCtx = avcodec_alloc_context3(pCodec);
if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar) < 0) {
fprintf(stderr, "Failed to copy codec parameters to decoder context\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
fprintf(stderr, "Failed to open codec\n");
return -1;
}
pFrame = av_frame_alloc();
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
if (!screen) {
fprintf(stderr, "SDL: could not set video mode - exiting\n");
exit(1);
}
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen);
sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL);
video_tid = SDL_CreateThread(video_thread, NULL);
while (!quit) {
SDL_WaitEvent(&event);
switch (event.type) {
case SDL_QUIT:
quit = 1;
break;
default:
break;
}
}
SDL_Quit();
avcodec_close(pCodecCtx);
av_free(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}
int video_thread(void *arg)
{
AVFormatContext *pFormatCtx = NULL;
int i, videoStream;
AVCodecContext *pCodecCtxOrig = NULL;
AVCodecContext *pCodecCtx = NULL;
AVCodec *pCodec = NULL;
AVFrame *pFrame = NULL;
AVPacket packet;
int frameFinished;
struct SwsContext *sws_ctx = NULL;
SDL_Surface *screen = NULL;
SDL_Overlay *bmp = NULL;
SDL_Rect rect;
SDL_Event event;
int videoWidth, videoHeight;
Uint32 pixformat;
char *filename = "rtsp://192.168.1.100:554/av0_0";
int ret;
av_register_all();
avformat_network_init();
pFormatCtx = avformat_alloc_context();
if (avformat_open_input(&pFormatCtx, filename, NULL, NULL) != 0) {
fprintf(stderr, "Cannot open input file\n");
return -1;
}
if (avformat_find_stream_info(pFormatCtx, NULL) < 0) {
fprintf(stderr, "Cannot find stream information\n");
return -1;
}
videoStream = -1;
for (i = 0; i < pFormatCtx->nb_streams; i++) {
if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {
videoStream = i;
break;
}
}
if (videoStream == -1) {
fprintf(stderr, "Cannot find a video stream\n");
return -1;
}
pCodecCtxOrig = pFormatCtx->streams[videoStream]->codec;
pCodec = avcodec_find_decoder(pCodecCtxOrig->codec_id);
if (pCodec == NULL) {
fprintf(stderr, "Unsupported codec\n");
return -1;
}
pCodecCtx = avcodec_alloc_context3(pCodec);
if (avcodec_parameters_to_context(pCodecCtx, pFormatCtx->streams[videoStream]->codecpar) < 0) {
fprintf(stderr, "Failed to copy codec parameters to decoder context\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
fprintf(stderr, "Failed to open codec\n");
return -1;
}
pFrame = av_frame_alloc();
screen = SDL_SetVideoMode(pCodecCtx->width, pCodecCtx->height, 0, 0);
if (!screen) {
fprintf(stderr, "SDL: could not set video mode - exiting\n");
exit(1);
}
bmp = SDL_CreateYUVOverlay(pCodecCtx->width, pCodecCtx->height, SDL_YV12_OVERLAY, screen);
sws_ctx = sws_getContext(pCodecCtx->width, pCodecCtx->height, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, PIX_FMT_YUV420P, SWS_BILINEAR, NULL, NULL, NULL);
while (av_read_frame(pFormatCtx, &packet) >= 0) {
if (packet.stream_index == videoStream) {
ret = avcodec_send_packet(pCodecCtx, &packet);
if (ret < 0) {
fprintf(stderr, "Error sending a packet for decoding\n");
break;
}
while (ret >= 0) {
ret = avcodec_receive_frame(pCodecCtx, pFrame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
break;
} else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
break;
}
sws_scale(sws_ctx, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, bmp->pixels, bmp->pitches);
rect.x = 0;
rect.y = 0;
rect.w = pCodecCtx->width;
rect.h = pCodecCtx->height;
SDL_DisplayYUVOverlay(bmp, &rect);
}
}
av_packet_unref(&packet);
if (quit) {
break;
}
}
avcodec_close(pCodecCtx);
av_free(pCodecCtx);
avformat_close_input(&pFormatCtx);
return 0;
}
阅读全文