FFmpeg RTSP 推流:C++ 代码实现
// 初始化FFmpeg库\n av_register_all();\n avformat_network_init();\n \n // 打开视频文件\n AVFormatContext *formatContext = avformat_alloc_context();\n if (avformat_open_input(&formatContext, "path/to/your/mp4/file.mp4", nullptr, nullptr) != 0) {\n qDebug() << "Failed to open video file";\n return -1;\n }\n \n // 查找视频流\n if (avformat_find_stream_info(formatContext, nullptr) < 0) {\n qDebug() << "Failed to find video stream";\n return -1;\n }\n \n int videoStreamIndex = -1;\n for (int i = 0; i < formatContext->nb_streams; i++) {\n if (formatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) {\n videoStreamIndex = i;\n break;\n }\n }\n \n if (videoStreamIndex == -1) {\n qDebug() << "Failed to find video stream";\n return -1;\n }\n \n // 获取视频流的解码器上下文\n AVCodecContext *codecContext = avcodec_alloc_context3(nullptr);\n avcodec_parameters_to_context(codecContext, formatContext->streams[videoStreamIndex]->codecpar);\n \n // 查找解码器\n AVCodec *codec = avcodec_find_decoder(codecContext->codec_id);\n if (codec == nullptr) {\n qDebug() << "Failed to find video decoder";\n return -1;\n }\n \n // 打开解码器\n if (avcodec_open2(codecContext, codec, nullptr) < 0) {\n qDebug() << "Failed to open video decoder";\n return -1;\n }\n \n // 创建视频帧\n AVFrame *frame = av_frame_alloc();\n AVFrame *rgbFrame = av_frame_alloc();\n \n // 计算帧大小\n int numBytes = av_image_get_buffer_size(AV_PIX_FMT_RGB24, codecContext->width, codecContext->height, 1);\n uint8_t *buffer = (uint8_t *)av_malloc(numBytes * sizeof(uint8_t));\n \n // 分配帧缓冲区\n av_image_fill_arrays(rgbFrame->data, rgbFrame->linesize, buffer, AV_PIX_FMT_RGB24, codecContext->width, codecContext->height, 1);\n \n // 创建图像转换上下文\n struct SwsContext *swsContext = sws_getContext(codecContext->width, codecContext->height, codecContext->pix_fmt, \n codecContext->width, codecContext->height, AV_PIX_FMT_RGB24, \n SWS_BILINEAR, nullptr, nullptr, nullptr);\n \n // 创建RTSP流的上下文\n AVFormatContext *rtspFormatContext = avformat_alloc_context();\n \n // 设置RTSP流的输出格式\n AVOutputFormat *outputFormat = av_guess_format("rtsp", nullptr, nullptr);\n rtspFormatContext->oformat = outputFormat;\n \n // 打开RTSP流\n if (avio_open(&rtspFormatContext->pb, RTSP_URL, AVIO_FLAG_WRITE) < 0) {\n qDebug() << "Failed to open RTSP stream";\n return -1;\n }\n \n // 添加视频流到RTSP流\n AVStream *rtspStream = avformat_new_stream(rtspFormatContext, nullptr);\n avcodec_parameters_copy(rtspStream->codecpar, codecContext->codecpar);\n rtspStream->codecpar->codec_tag = 0;\n rtspStream->time_base = codecContext->time_base;\n \n // 写入RTSP流的头部\n avformat_write_header(rtspFormatContext, nullptr);\n \n // 定义开始时间\n qint64 startTime = QDateTime::currentMSecsSinceEpoch();\n \n // 推送视频流到RTSP服务器\n AVPacket packet;\n while (av_read_frame(formatContext, &packet) >= 0) {\n if (packet.stream_index == videoStreamIndex) {\n // 解码视频帧\n if (avcodec_send_packet(codecContext, &packet) >= 0) {\n while (avcodec_receive_frame(codecContext, frame) >= 0) {\n // 转换图像格式\n sws_scale(swsContext, frame->data, frame->linesize, 0, codecContext->height, rgbFrame->data, rgbFrame->linesize);\n \n // 设置时间戳\n qint64 currentTime = QDateTime::currentMSecsSinceEpoch() - startTime;\n rgbFrame->pts = av_rescale_q(currentTime, AV_TIME_BASE_Q, codecContext->time_base);\n \n // 编码并写入RTSP流\n av_interleaved_write_frame(rtspFormatContext, &packet);\n }\n }\n }\n \n av_packet_unref(&packet);\n }\n \n // 写入RTSP流的尾部\n av_write_trailer(rtspFormatContext);\n \n // 清理资源\n avformat_free_context(formatContext);\n avcodec_free_context(&codecContext);\n av_frame_free(&frame);\n av_frame_free(&rgbFrame);\n av_free(buffer);\n avformat_free_context(rtspFormatContext);
原文地址: https://www.cveoy.top/t/topic/pxeK 著作权归作者所有。请勿转载和采集!