C++实现ffmpeg推rtsp流

时间: 2023-10-20 11:08:58 浏览: 48
要在C语言中实现FFmpeg推送RTSP流,需要遵循以下步骤: 1. 初始化FFmpeg库 ```c #include <libavutil/avutil.h> #include <libavformat/avformat.h> av_register_all(); avformat_network_init(); ``` 2. 打开输入文件或设备 ```c AVFormatContext *input_ctx = avformat_alloc_context(); AVInputFormat *input_fmt = av_find_input_format("video4linux2"); avformat_open_input(&input_ctx, "video device", input_fmt, NULL); avformat_find_stream_info(input_ctx, NULL); ``` 3. 创建输出上下文 ```c AVFormatContext *output_ctx = NULL; avformat_alloc_output_context2(&output_ctx, NULL, "rtsp", "rtsp://server_address/live"); ``` 4. 添加音视频流 ```c AVStream *in_stream = input_ctx->streams[0]; AVStream *out_stream = avformat_new_stream(output_ctx, NULL); avcodec_parameters_copy(out_stream->codecpar, in_stream->codecpar); out_stream->codecpar->codec_tag = 0; ``` 5. 打开输出流 ```c avio_open(&output_ctx->pb, "rtsp://server_address/live", AVIO_FLAG_WRITE); avformat_write_header(output_ctx, NULL); ``` 6. 推送音视频数据 ```c AVPacket pkt; while(av_read_frame(input_ctx, &pkt) == 0) { pkt.stream_index = 0; av_interleaved_write_frame(output_ctx, &pkt); } ``` 7. 关闭输出流和输入文件或设备 ```c av_write_trailer(output_ctx); avio_close(output_ctx->pb); avformat_free_context(output_ctx); avformat_close_input(&input_ctx); ``` 注意事项: - 本示例仅适用于单路音视频流推送; - 需要安装FFmpeg库和对应的编解码器; - 需要在编译时链接FFmpeg库。

相关推荐

要使用C实现ffmpeg推rtsp流,需要使用ffmpeg库来处理视频和音频数据,并使用libavformat库来处理rtsp协议。以下是一个基本的示例代码: c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include #include int main(int argc, char **argv) { AVFormatContext *input_ctx = NULL, *output_ctx = NULL; AVCodecContext *codec_ctx = NULL; AVCodecParameters *codec_params = NULL; AVStream *input_stream = NULL, *output_stream = NULL; AVPacket packet; int ret, i; // Open input RTSP stream if ((ret = avformat_open_input(&input_ctx, "rtsp://localhost:8554/test", NULL, NULL)) < 0) { fprintf(stderr, "Cannot open input RTSP stream\n"); return ret; } // Get stream info if ((ret = avformat_find_stream_info(input_ctx, NULL)) < 0) { fprintf(stderr, "Cannot get input stream info\n"); return ret; } // Find video stream for (i = 0; i < input_ctx->nb_streams; i++) { if (input_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { input_stream = input_ctx->streams[i]; break; } } if (!input_stream) { fprintf(stderr, "Cannot find video stream\n"); return AVERROR_EXIT; } // Open output file if ((ret = avformat_alloc_output_context2(&output_ctx, NULL, NULL, "rtsp://localhost:8555/test")) < 0) { fprintf(stderr, "Cannot open output RTSP stream\n"); return ret; } // Add video stream codec_params = input_stream->codecpar; output_stream = avformat_new_stream(output_ctx, NULL); codec_ctx = avcodec_alloc_context3(NULL); avcodec_parameters_to_context(codec_ctx, codec_params); codec_ctx->codec_tag = 0; av_opt_set(codec_ctx->priv_data, "preset", "ultrafast", 0); avcodec_open2(codec_ctx, NULL, NULL); avcodec_parameters_from_context(output_stream->codecpar, codec_ctx); av_dump_format(output_ctx, 0, "rtsp", 1); if (!output_stream) { fprintf(stderr, "Cannot add output video stream\n"); return AVERROR_EXIT; } // Open output RTSP stream if (!(output_ctx->oformat->flags & AVFMT_NOFILE)) { if ((ret = avio_open(&output_ctx->pb, "rtsp://localhost:8555/test", AVIO_FLAG_WRITE)) < 0) { fprintf(stderr, "Cannot open output RTSP stream\n"); return ret; } } // Write header if ((ret = avformat_write_header(output_ctx, NULL)) < 0) { fprintf(stderr, "Cannot write output header\n"); return ret; } // Loop through input packets while (1) { if ((ret = av_read_frame(input_ctx, &packet)) < 0) break; if (packet.stream_index != input_stream->index) continue; // Write packet av_packet_rescale_ts(&packet, input_stream->time_base, output_stream->time_base); packet.pos = -1; av_interleaved_write_frame(output_ctx, &packet); av_packet_unref(&packet); } // Write trailer av_write_trailer(output_ctx); // Finish avformat_close_input(&input_ctx); if (output_ctx && !(output_ctx->oformat->flags & AVFMT_NOFILE)) avio_closep(&output_ctx->pb); avformat_free_context(output_ctx); avcodec_free_context(&codec_ctx); return 0; } 这个示例代码打开一个RTSP输入流,找到视频流,然后创建一个RTSP输出流并添加视频流。然后,它循环读取输入数据包并将其写入输出流。最后,它写入输出文件的尾随数据并清理资源。 请注意,这只是一个基本的示例代码,您可能需要进行更多的调整和错误处理以适应您的特定用例。
以下是使用FFmpeg实现RTSP推流的C++代码示例: c++ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <signal.h> #include #include <errno.h> #include #include #include const char* RTSP_URL = "rtsp://192.168.1.1:8554/test"; // 要推流的RTSP地址 const int FRAME_RATE = 25; // 视频帧率 const int VIDEO_WIDTH = 640; // 视频宽度 const int VIDEO_HEIGHT = 480; // 视频高度 int64_t start_time = 0; int interrupt_cb(void* ctx) { int timeout = 10; if (av_gettime_relative() - start_time > timeout * 1000 * 1000) { return 1; } return 0; } void* push_thread(void* arg) { AVFormatContext* fmt_ctx = NULL; AVStream* video_stream = NULL; AVCodecContext* codec_ctx = NULL; AVCodec* codec = NULL; AVFrame* frame = NULL; AVPacket pkt; int ret = 0; avformat_network_init(); // 打开输出RTSP流的上下文 avformat_alloc_output_context2(&fmt_ctx, NULL, "rtsp", RTSP_URL); if (!fmt_ctx) { printf("avformat_alloc_output_context2 failed\n"); goto end; } // 找到h.264编码器 codec = avcodec_find_encoder_by_name("libx264"); if (!codec) { printf("avcodec_find_encoder_by_name failed\n"); goto end; } // 创建视频流 video_stream = avformat_new_stream(fmt_ctx, codec); if (!video_stream) { printf("avformat_new_stream failed\n"); goto end; } video_stream->codecpar->codec_id = codec->id; video_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; video_stream->codecpar->width = VIDEO_WIDTH; video_stream->codecpar->height = VIDEO_HEIGHT; video_stream->codecpar->format = AV_PIX_FMT_YUV420P; video_stream->codecpar->bit_rate = 500000; video_stream->codecpar->fps_num = FRAME_RATE; video_stream->codecpar->fps_den = 1; // 打开编码器 codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { printf("avcodec_alloc_context3 failed\n"); goto end; } avcodec_parameters_to_context(codec_ctx, video_stream->codecpar); if (avcodec_open2(codec_ctx, codec, NULL) < 0) { printf("avcodec_open2 failed\n"); goto end; } // 创建帧 frame = av_frame_alloc(); if (!frame) { printf("av_frame_alloc failed\n"); goto end; } frame->format = codec_ctx->pix_fmt; frame->width = VIDEO_WIDTH; frame->height = VIDEO_HEIGHT; if (av_frame_get_buffer(frame, 32) < 0) { printf("av_frame_get_buffer failed\n"); goto end; } // 打开输出流 if (avio_open(&fmt_ctx->pb, RTSP_URL, AVIO_FLAG_WRITE) < 0) { printf("avio_open failed\n"); goto end; } // 写输出流头部 avformat_write_header(fmt_ctx, NULL); // 推流 while (1) { // 生成测试图像 uint8_t* data[1]; int linesize[1]; int y_size = VIDEO_WIDTH * VIDEO_HEIGHT; data[0] = (uint8_t*)malloc(y_size * 3 / 2); memset(data[0], 0, y_size * 3 / 2); for (int i = 0; i < VIDEO_HEIGHT; i++) { memset(data[0] + i * VIDEO_WIDTH, i * 255 / (VIDEO_HEIGHT - 1), VIDEO_WIDTH); } for (int i = 0; i < VIDEO_HEIGHT / 2; i++) { memset(data[0] + y_size + i * VIDEO_WIDTH / 2, 128 + i * 127 / (VIDEO_HEIGHT / 2 - 1), VIDEO_WIDTH / 2); } // 将测试图像转换为AVFrame av_image_fill_arrays(frame->data, frame->linesize, data[0], codec_ctx->pix_fmt, VIDEO_WIDTH, VIDEO_HEIGHT, 32); frame->pts = av_rescale_q(av_gettime_relative() - start_time, (AVRational){1, AV_TIME_BASE}, video_stream->time_base); ret = avcodec_send_frame(codec_ctx, frame); if (ret < 0) { printf("avcodec_send_frame failed\n"); goto end; } while (ret >= 0) { ret = avcodec_receive_packet(codec_ctx, &pkt); if (ret < 0) { break; } av_packet_rescale_ts(&pkt, codec_ctx->time_base, video_stream->time_base); pkt.stream_index = video_stream->index; av_interleaved_write_frame(fmt_ctx, &pkt); av_packet_unref(&pkt); } free(data[0]); if (av_gettime_relative() - start_time > 30 * 1000 * 1000) { // 推流30秒后退出 break; } } // 写输出流尾部 av_write_trailer(fmt_ctx); end: if (frame) { av_frame_free(&frame); } if (codec_ctx) { avcodec_free_context(&codec_ctx); } if (fmt_ctx) { avio_close(fmt_ctx->pb); avformat_free_context(fmt_ctx); } return NULL; } int main(int argc, char* argv[]) { pthread_t pid; int ret = 0; // 初始化FFmpeg库 av_register_all(); avformat_network_init(); avcodec_register_all(); start_time = av_gettime_relative(); // 创建推流线程 ret = pthread_create(&pid, NULL, push_thread, NULL); if (ret != 0) { printf("pthread_create failed\n"); return -1; } // 等待推流线程退出 pthread_join(pid, NULL); return 0; } 上述代码中使用libx264编码器,生成测试图像并将其推流到RTSP服务器。可以根据实际需要修改RTSP_URL、FRAME_RATE、VIDEO_WIDTH和VIDEO_HEIGHT等参数。
在 C++ 中使用 FFmpeg 进行 RTSP 推流,主要需要以下步骤: 1. 初始化 FFmpeg 库:调用 av_register_all() 函数注册 FFmpeg 库中的所有可用文件格式和编解码器。 2. 打开输入流:调用 avformat_open_input() 函数打开 RTSP 输入流,获取输入流的相关信息。 3. 查找视频流:调用 avformat_find_stream_info() 函数查找视频流的相关信息。 4. 查找编码器:调用 avcodec_find_encoder() 函数查找编码器,以便将视频流编码为指定格式。 5. 创建输出格式上下文:调用 avformat_alloc_output_context2() 函数创建输出格式上下文。 6. 添加视频流:调用 avformat_new_stream() 函数创建一个新的视频流。 7. 打开输出流:调用 avio_open2() 函数打开输出流。 8. 写文件头:调用 avformat_write_header() 函数将输出格式上下文中的头部信息写入输出流中。 9. 循环读取视频帧:调用 av_read_frame() 函数循环读取视频帧。 10. 编码视频帧:调用 avcodec_encode_video2() 函数将读取的视频帧编码为指定格式。 11. 写入编码后的帧数据:调用 av_write_frame() 函数将编码后的帧数据写入输出流中。 12. 写文件尾:调用 av_write_trailer() 函数将输出格式上下文的尾部信息写入输出流中。 13. 释放资源:释放所有资源。 以下是一个简单的示例代码: C++ #include <iostream> #include <cstdlib> #include <cstring> #include <cstdio> #include <unistd.h> extern "C" { #include #include #include #include #include #include } #define RTSP_URL "rtsp://localhost:8554/test.sdp" // RTSP 输入地址 #define OUTPUT_URL "rtmp://localhost:1935/live/test" // RTMP 输出地址 int main(int argc, char *argv[]) { av_register_all(); // 注册所有可用文件格式和编解码器 AVFormatContext *ifmt_ctx = NULL; int ret = 0; // 打开 RTSP 输入流 if ((ret = avformat_open_input(&ifmt_ctx, RTSP_URL, NULL, NULL)) < 0) { std::cerr << "Could not open input stream " << RTSP_URL << std::endl; return ret; } // 查找视频流信息 if ((ret = avformat_find_stream_info(ifmt_ctx, NULL)) < 0) { std::cerr << "Could not find stream information" << std::endl; return ret; } AVCodecContext *codec_ctx = NULL; AVCodec *codec = NULL; // 查找 H.264 编码器 codec = avcodec_find_encoder_by_name("libx264"); if (!codec) { std::cerr << "Could not find h264 encoder" << std::endl; return AVERROR(EINVAL); } // 创建编码器上下文 codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { std::cerr << "Could not allocate codec context" << std::endl; return AVERROR(ENOMEM); } // 设置编码器参数 codec_ctx->codec_id = codec->id; codec_ctx->bit_rate = 400000; codec_ctx->width = 640; codec_ctx->height = 480; codec_ctx->time_base = {1, 25}; codec_ctx->gop_size = 10; codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; // 打开编码器 if ((ret = avcodec_open2(codec_ctx, codec, NULL)) < 0) { std::cerr << "Could not open codec" << std::endl; return ret; } AVFormatContext *ofmt_ctx = NULL; AVOutputFormat *ofmt = NULL; // 创建输出格式上下文 avformat_alloc_output_context2(&ofmt_ctx, NULL, "flv", OUTPUT_URL); ofmt = ofmt_ctx->oformat; // 添加视频流 AVStream *out_stream = avformat_new_stream(ofmt_ctx, NULL); out_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; out_stream->codecpar->codec_id = codec_ctx->codec_id; out_stream->codecpar->bit_rate = codec_ctx->bit_rate; out_stream->codecpar->width = codec_ctx->width; out_stream->codecpar->height = codec_ctx->height; avcodec_parameters_from_context(out_stream->codecpar, codec_ctx); // 打开输出流 if (!(ofmt->flags & AVFMT_NOFILE)) { if ((ret = avio_open2(&ofmt_ctx->pb, OUTPUT_URL, AVIO_FLAG_WRITE, NULL, NULL)) < 0) { std::cerr << "Could not open output URL " << OUTPUT_URL << std::endl; return ret; } } // 写文件头 if ((ret = avformat_write_header(ofmt_ctx, NULL)) < 0) { std::cerr << "Error writing header" << std::endl; return ret; } int video_stream_index = 0; AVPacket pkt = {0}; // 循环读取视频帧 while (true) { if ((ret = av_read_frame(ifmt_ctx, &pkt)) < 0) { break; } if (pkt.stream_index == video_stream_index) { // 编码视频帧 if ((ret = avcodec_send_packet(codec_ctx, &pkt)) < 0) { std::cerr << "Error sending packet to encoder" << std::endl; break; } // 写入编码后的帧数据 while (ret >= 0) { ret = avcodec_receive_frame(codec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { std::cerr << "Error receiving frame from encoder" << std::endl; goto end; } av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; // 将编码后的帧数据写入输出流 if ((ret = avcodec_send_frame(codec_ctx, frame)) < 0) { std::cerr << "Error sending frame to encoder" << std::endl; goto end; } while (ret >= 0) { ret = avcodec_receive_packet(codec_ctx, &pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { std::cerr << "Error receiving packet from encoder" << std::endl; goto end; } av_packet_rescale_ts(&pkt, codec_ctx->time_base, out_stream->time_base); pkt.stream_index = video_stream_index; if ((ret = av_write_frame(ofmt_ctx, &pkt)) < 0) { std::cerr << "Error writing packet to output stream" << std::endl; goto end; } } av_packet_unref(&pkt); } } av_packet_unref(&pkt); } // 写文件尾 av_write_trailer(ofmt_ctx); end: // 释放资源 avcodec_free_context(&codec_ctx); avformat_close_input(&ifmt_ctx); avformat_free_context(ofmt_ctx); return 0; } 需要注意的是,该示例代码并未完全测试,仅供参考,具体实现还需要根据实际情况进行调整。同时,需要注意 FFmpeg 的版本问题,不同版本的 API 可能存在差异。
以下是使用FFmpeg实现RTSP推流的示例C代码: #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include #include int main(int argc, char **argv) { AVFormatContext *fmt_ctx = NULL; AVOutputFormat *out_fmt = NULL; AVStream *video_st = NULL; AVCodecContext *codec_ctx = NULL; AVCodec *codec = NULL; AVDictionary *options = NULL; int ret; const char *rtsp_url = "rtsp://your_rtsp_server_url"; const char *out_filename = "rtsp_stream_output"; // Register all available codecs and formats av_register_all(); avformat_network_init(); // Allocate output format context avformat_alloc_output_context2(&fmt_ctx, NULL, "rtsp", out_filename); if (!fmt_ctx) { fprintf(stderr, "Could not create output format context\n"); return -1; } // Find video encoder codec codec = avcodec_find_encoder_by_name("h264"); if (!codec) { fprintf(stderr, "Could not find video encoder codec\n"); return -1; } // Allocate codec context and set options codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { fprintf(stderr, "Could not allocate codec context\n"); return -1; } codec_ctx->bit_rate = 400000; codec_ctx->width = 640; codec_ctx->height = 480; codec_ctx->time_base = (AVRational){1, 25}; codec_ctx->gop_size = 10; codec_ctx->pix_fmt = AV_PIX_FMT_YUV420P; av_opt_set(codec_ctx->priv_data, "preset", "ultrafast", 0); av_opt_set(codec_ctx->priv_data, "tune", "zerolatency", 0); // Open codec if ((ret = avcodec_open2(codec_ctx, codec, &options)) < 0) { fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret)); return -1; } // Add video stream to output format context video_st = avformat_new_stream(fmt_ctx, codec); if (!video_st) { fprintf(stderr, "Could not create new video stream\n"); return -1; } avcodec_parameters_from_context(video_st->codecpar, codec_ctx); // Open output file or URL if ((ret = avio_open(&fmt_ctx->pb, rtsp_url, AVIO_FLAG_WRITE)) < 0) { fprintf(stderr, "Could not open output file or URL: %s\n", av_err2str(ret)); return -1; } // Write header to output format context if ((ret = avformat_write_header(fmt_ctx, &options)) < 0) { fprintf(stderr, "Could not write header to output format context: %s\n", av_err2str(ret)); return -1; } // Main loop to write video frames for (int i = 0; i < 1000; i++) { AVFrame *frame = av_frame_alloc(); if (!frame) { fprintf(stderr, "Could not allocate video frame\n"); return -1; } // Fill video frame with data // ... // Set frame PTS and duration frame->
### 回答1: ffmpeg可以用来进行rtsp推流。在C语言中,我们可以使用ffmpeg提供的C API来实现这个功能。 首先,我们需要初始化ffmpeg。这可以通过使用av_register_all()函数来完成。接下来,我们需要创建一个AVFormatContext,来包含所有的推流相关的信息,例如推流的URL、视频编码器等。 之后,我们需要设置视频编码器参数,例如视频分辨率、码率、帧率等。这可以通过使用AVCodecParameters和AVCodecContext来完成。 然后,我们需要打开推流的URL,并将相关信息存入AVFormatContext。这可以通过使用avio_open2()函数来完成。 之后,我们需要开始推流。这可以通过使用avformat_write_header()函数和av_write_frame()函数来完成。 最后,我们需要关闭推流,并释放相关资源。这可以通过使用av_write_trailer()函数和avformat_free_context()函数来完成。 使用ffmpeg来实现rtsp推流,可以实现高效稳定地推流视频和音频数据。但是,在使用过程中需要注意正确设置相关参数,以保证推流的成功。 ### 回答2: FFmpeg是一款开源的跨平台多媒体框架,支持音视频的编解码、推拉流、调整视频尺寸等功能,因此成为了很多嵌入式设备、视频处理软件以及直播平台的选择。 RTSP(Real Time Streaming Protocol)是一种用于实时流媒体传输的协议,是一种客户端/服务器协议,用于控制流媒体服务器上的视频或音频。该协议通常在视频监控、视频会议等领域得到广泛应用。 通过FFmpeg,我们可以使用C语言来推送RTSP流。实现方法主要包括以下步骤: 1. 首先需要打开RTSP协议的输入文件或流,即对应打开rtsp URL。 2. 使用AVFormatContext来生成一个输出流,并设置音视频的编码格式等参数。 3. 通过avio_open2方法打开URL,建立RTSP传输连接。 4. 使用avformat_write_header方法向RTSP服务器发送数据包头。 5. 通过av_read_frame和av_write_frame方法读取输入流中的音视频数据包,并将它们转换成输出流中相应的格式,并使用av_write_frame方法将数据包写入RTSP流中。 6. 当数据流结束时,通过av_write_trailer方法清空缓存并释放资源。 总之,通过FFmpeg可以方便地利用C语言实现RTSP推流,让我们可以在视频监控等领域对流媒体进行高效的传输和处理。
使用 FFmpeg C++ API 实现 RTSP 拉流并推流需要以下步骤: 1. 初始化 FFmpeg 库和 AVFormatContext。 cpp av_register_all(); avformat_network_init(); AVFormatContext *inputContext = avformat_alloc_context(); 2. 打开 RTSP 流并读取媒体信息。 cpp if (avformat_open_input(&inputContext, "rtsp://example.com/stream", nullptr, nullptr) != 0) { // 处理打开 RTSP 流失败的情况 } if (avformat_find_stream_info(inputContext, nullptr) < 0) { // 处理读取媒体信息失败的情况 } 3. 查找视频流和音频流,并为它们分配解码器。 cpp int videoStreamIndex = -1; int audioStreamIndex = -1; for (int i = 0; i < inputContext->nb_streams; i++) { AVStream *stream = inputContext->streams[i]; AVCodecParameters *codecParameters = stream->codecpar; AVCodec *codec = avcodec_find_decoder(codecParameters->codec_id); if (!codec) { continue; } if (codecParameters->codec_type == AVMEDIA_TYPE_VIDEO && videoStreamIndex < 0) { videoStreamIndex = i; AVCodecContext *codecContext = avcodec_alloc_context3(codec); avcodec_parameters_to_context(codecContext, codecParameters); avcodec_open2(codecContext, codec, nullptr); // 处理视频流 } else if (codecParameters->codec_type == AVMEDIA_TYPE_AUDIO && audioStreamIndex < 0) { audioStreamIndex = i; AVCodecContext *codecContext = avcodec_alloc_context3(codec); avcodec_parameters_to_context(codecContext, codecParameters); avcodec_open2(codecContext, codec, nullptr); // 处理音频流 } } if (videoStreamIndex < 0 || audioStreamIndex < 0) { // 处理找不到视频流或音频流的情况 } 4. 创建输出 AVFormatContext,并为视频流和音频流添加编码器。 cpp AVFormatContext *outputContext = avformat_alloc_context(); avformat_alloc_output_context2(&outputContext, nullptr, "flv", "rtmp://example.com/live"); if (!outputContext) { // 处理创建输出 AVFormatContext 失败的情况 } AVStream *videoStream = avformat_new_stream(outputContext, nullptr); AVStream *audioStream = avformat_new_stream(outputContext, nullptr); if (!videoStream || !audioStream) { // 处理创建输出流失败的情况 } AVCodecContext *videoCodecContext = avcodec_alloc_context3(nullptr); AVCodecContext *audioCodecContext = avcodec_alloc_context3(nullptr); if (!videoCodecContext || !audioCodecContext) { // 处理创建编码器上下文失败的情况 } videoCodecContext->codec_id = AV_CODEC_ID_H264; videoCodecContext->codec_type = AVMEDIA_TYPE_VIDEO; videoCodecContext->pix_fmt = AV_PIX_FMT_YUV420P; videoCodecContext->width = 1280; videoCodecContext->height = 720; videoCodecContext->time_base = {1, 25}; audioCodecContext->codec_id = AV_CODEC_ID_AAC; audioCodecContext->codec_type = AVMEDIA_TYPE_AUDIO; audioCodecContext->sample_rate = 44100; audioCodecContext->channels = 2; audioCodecContext->channel_layout = AV_CH_LAYOUT_STEREO; audioCodecContext->time_base = {1, 44100}; if (avcodec_open2(videoCodecContext, avcodec_find_encoder(videoCodecContext->codec_id), nullptr) < 0 || avcodec_open2(audioCodecContext, avcodec_find_encoder(audioCodecContext->codec_id), nullptr) < 0) { // 处理打开编码器失败的情况 } avcodec_parameters_from_context(videoStream->codecpar, videoCodecContext); avcodec_parameters_from_context(audioStream->codecpar, audioCodecContext); 5. 打开输出流并写入媒体头。 cpp if (!(outputContext->oformat->flags & AVFMT_NOFILE)) { if (avio_open(&outputContext->pb, "rtmp://example.com/live", AVIO_FLAG_WRITE) < 0) { // 处理打开输出流失败的情况 } } if (avformat_write_header(outputContext, nullptr) < 0) { // 处理写入媒体头失败的情况 } 6. 读取 RTSP 流中的帧并写入输出流。 cpp AVPacket packet; av_init_packet(&packet); while (av_read_frame(inputContext, &packet) == 0) { AVStream *inputStream = inputContext->streams[packet.stream_index]; AVStream *outputStream = outputContext->streams[packet.stream_index]; if (packet.stream_index == videoStreamIndex) { packet.pts = av_rescale_q(packet.pts, inputStream->time_base, videoStream->time_base); packet.dts = av_rescale_q(packet.dts, inputStream->time_base, videoStream->time_base); packet.duration = av_rescale_q(packet.duration, inputStream->time_base, videoStream->time_base); packet.pos = -1; av_interleaved_write_frame(outputContext, &packet); } else if (packet.stream_index == audioStreamIndex) { packet.pts = av_rescale_q(packet.pts, inputStream->time_base, audioStream->time_base); packet.dts = av_rescale_q(packet.dts, inputStream->time_base, audioStream->time_base); packet.duration = av_rescale_q(packet.duration, inputStream->time_base, audioStream->time_base); packet.pos = -1; av_interleaved_write_frame(outputContext, &packet); } av_packet_unref(&packet); } 7. 写入媒体尾并释放资源。 cpp av_write_trailer(outputContext); avcodec_free_context(&videoCodecContext); avcodec_free_context(&audioCodecContext); avformat_close_input(&inputContext); avformat_free_context(inputContext); avformat_free_context(outputContext); 以上就是使用 FFmpeg C++ API 实现 RTSP 拉流并推流的流程。需要注意的是,这只是一个简单的示例,实际的情况可能会更加复杂。
你可以使用 FFmpeg 的 C++ API 来进行 RTSP 推流。下面是一个简单的示例代码: c++ #include <iostream> #include <string> #include <chrono> #include <thread> extern "C" { #include #include #include #include } int main(int argc, char *argv[]) { int ret = 0; // 初始化 FFmpeg av_register_all(); avformat_network_init(); // 打开输入文件 AVFormatContext *input_ctx = NULL; if ((ret = avformat_open_input(&input_ctx, "input.mp4", NULL, NULL)) < 0) { std::cerr << "Error: could not open input file" << std::endl; return ret; } // 获取视频流信息 if ((ret = avformat_find_stream_info(input_ctx, NULL)) < 0) { std::cerr << "Error: could not find stream information" << std::endl; return ret; } // 获取视频流索引 int video_stream_index = -1; for (int i = 0; i < input_ctx->nb_streams; i++) { if (input_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_index = i; break; } } if (video_stream_index == -1) { std::cerr << "Error: could not find video stream" << std::endl; return AVERROR(EINVAL); } // 打开输出文件 AVFormatContext *output_ctx = NULL; if ((ret = avformat_alloc_output_context2(&output_ctx, NULL, "rtsp", "rtsp://localhost:8554/test")) < 0) { std::cerr << "Error: could not create output context" << std::endl; return ret; } // 添加视频流 AVStream *video_out = avformat_new_stream(output_ctx, NULL); if (!video_out) { std::cerr << "Error: could not create output stream" << std::endl; return AVERROR_UNKNOWN; } // 复制参数 if ((ret = avcodec_parameters_copy(video_out->codecpar, input_ctx->streams[video_stream_index]->codecpar)) < 0) { std::cerr << "Error: could not copy codec parameters" << std::endl; return ret; } // 打开输出流 if (!(output_ctx->oformat->flags & AVFMT_NOFILE)) { if ((ret = avio_open(&output_ctx->pb, "rtsp://localhost:8554/test", AVIO_FLAG_WRITE)) < 0) { std::cerr << "Error: could not open output file" << std::endl; return ret; } } // 写文件头 if ((ret = avformat_write_header(output_ctx, NULL)) < 0) { std::cerr << "Error: could not write output file header" << std::endl; return ret; } // 编码和推流 AVPacket pkt; while (true) { // 读取一帧视频 AVFrame *frame = av_frame_alloc(); if (!frame) { std::cerr << "Error: could not allocate video frame" << std::endl; return AVERROR(ENOMEM); } AVPacket *packet = av_packet_alloc(); if (!packet) { std::cerr << "Error: could not allocate packet" << std::endl; return AVERROR(ENOMEM); } if ((ret = av_read_frame(input_ctx, packet)) < 0) { break; } if (packet->stream_index != video_stream_index) { continue; } if ((ret = avcodec_send_packet(input_ctx->streams[video_stream_index]->codecpar, packet)) < 0) { std::cerr << "Error: could not send packet to decoder" << std::endl; return ret; } while (ret >= 0) { ret = avcodec_receive_frame(input_ctx->streams[video_stream_index]->codecpar, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { std::cerr << "Error: could not receive frame from decoder" << std::endl; return ret; } // 转换像素格式 AVFrame *out_frame = av_frame_alloc(); if (!out_frame) { std::cerr << "Error: could not allocate output frame" << std::endl; return AVERROR(ENOMEM); } if ((ret = av_image_alloc(out_frame->data, out_frame->linesize, video_out->codecpar->width, video_out->codecpar->height, video_out->codecpar->format, 1)) < 0) { std::cerr << "Error: could not allocate image" << std::endl; return ret; } if ((ret = av_image_copy(out_frame->data, out_frame->linesize, (const uint8_t **)frame->data, frame->linesize, video_out->codecpar->format, video_out->codecpar->width, video_out->codecpar->height)) < 0) { std::cerr << "Error: could not copy image" << std::endl; return ret; } out_frame->format = video_out->codecpar->format; out_frame->width = video_out->codecpar->width; out_frame->height = video_out->codecpar->height; out_frame->pts = av_rescale_q(frame->pts, input_ctx->streams[video_stream_index]->time_base, video_out->time_base); out_frame->pkt_dts = av_rescale_q(frame->pkt_dts, input_ctx->streams[video_stream_index]->time_base, video_out->time_base); out_frame->pkt_duration = av_rescale_q(frame->pkt_duration, input_ctx->streams[video_stream_index]->time_base, video_out->time_base); // 编码 if ((ret = avcodec_send_frame(video_out->codecpar, out_frame)) < 0) { std::cerr << "Error: could not send frame to encoder" << std::endl; return ret; } while (ret >= 0) { ret = avcodec_receive_packet(video_out->codecpar, &pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { std::cerr << "Error: could not receive packet from encoder" << std::endl; return ret; } // 推流 av_packet_rescale_ts(&pkt, video_out->codecpar->time_base, video_out->time_base); pkt.stream_index = video_out->index; if ((ret = av_interleaved_write_frame(output_ctx, &pkt)) < 0) { std::cerr << "Error: could not write frame to output file" << std::endl; return ret; } av_packet_unref(&pkt); } av_frame_free(&out_frame); } av_packet_free(&packet); av_frame_free(&frame); } // 写文件尾 if ((ret = av_write_trailer(output_ctx)) < 0) { std::cerr << "Error: could not write output file trailer" << std::endl; return ret; } // 释放资源 avformat_close_input(&input_ctx); if (output_ctx && !(output_ctx->oformat->flags & AVFMT_NOFILE)) { avio_closep(&output_ctx->pb); } avformat_free_context(output_ctx); return 0; } 这个示例代码使用了 FFmpeg 的 C++ API 来打开一个 MP4 文件,将视频流推流到 RTSP 服务器。你需要根据你的实际情况进行修改。
以下是一个使用FFmpeg实现本地摄像头实时推流到RTSP服务器的C代码示例: c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include #include #include #include #include #define STREAM_DURATION 60.0 #define STREAM_FRAME_RATE 25 /* 25 images/s */ #define STREAM_PIX_FMT AV_PIX_FMT_YUV420P /* default pix_fmt */ int main(int argc, char **argv) { AVFormatContext *pFormatCtx = NULL; AVOutputFormat *pOutputFmt = NULL; AVStream *pStream = NULL; AVCodecContext *pCodecCtx = NULL; AVCodec *pCodec = NULL; AVDictionary *options = NULL; AVFrame *pFrame = NULL; int ret, i, x, y; int frame_count = 0, video_outbuf_size; FILE *f = NULL; /* Initialize libavcodec, and register all codecs and formats. */ av_register_all(); avdevice_register_all(); /* Open video input device */ AVInputFormat *inputFmt = av_find_input_format("video4linux2"); if ((ret = avformat_open_input(&pFormatCtx, "/dev/video0", inputFmt, NULL)) < 0) { fprintf(stderr, "Could not open input device\n"); return ret; } /* Retrieve stream information */ if (avformat_find_stream_info(pFormatCtx, NULL) < 0) { fprintf(stderr, "Could not find stream information\n"); return -1; } /* Find the first video stream */ for (i = 0; i < pFormatCtx->nb_streams; i++) { if (pFormatCtx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { pStream = pFormatCtx->streams[i]; break; } } if (!pStream) { fprintf(stderr, "Could not find video stream\n"); return -1; } /* Open output URL */ if ((ret = avformat_alloc_output_context2(&pFormatCtx, NULL, "rtsp", "rtsp://localhost:8554/test")) < 0) { fprintf(stderr, "Could not allocate output context\n"); return ret; } pOutputFmt = pFormatCtx->oformat; /* Add the video stream using the default format codec */ pCodec = avcodec_find_encoder(pOutputFmt->video_codec); if (!pCodec) { fprintf(stderr, "Codec not found\n"); return -1; } pCodecCtx = avcodec_alloc_context3(pCodec); if (!pCodecCtx) { fprintf(stderr, "Could not allocate codec context\n"); return -1; } /* Set stream parameters */ pCodecCtx->codec_id = pOutputFmt->video_codec; pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO; pCodecCtx->bit_rate = 400000; pCodecCtx->width = pStream->codecpar->width; pCodecCtx->height = pStream->codecpar->height; pCodecCtx->time_base = (AVRational){1, STREAM_FRAME_RATE}; pCodecCtx->pix_fmt = STREAM_PIX_FMT; /* Set the encoder's options */ av_dict_set(&options, "preset
推流是将视频流通过网络传输到远程服务器或者设备的过程,而RTSP(Real Time Streaming Protocol)是一种流媒体传输协议,可以用于实现视频直播和点播等功能。基于FFmpeg进行RTSP推流可以使用FFmpeg的库函数来实现,下面是一个简单的C++代码示例: C++ #include <iostream> #include <string> #include <unistd.h> #include <errno.h> extern "C" { #include #include #include #include #include #include } #define RTSP_URL "rtsp://192.168.1.1/live" int main(int argc, char *argv[]) { av_register_all(); avcodec_register_all(); AVFormatContext *fmt_ctx = nullptr; AVCodecContext *codec_ctx = nullptr; AVCodec *codec = nullptr; AVFrame *frame = nullptr; AVPacket pkt = {}; // 打开输入文件并读取流信息 int ret = avformat_open_input(&fmt_ctx, "input.mp4", nullptr, nullptr); if (ret < 0) { std::cerr << "avformat_open_input error: " << av_err2str(ret) << std::endl; return 1; } // 检索流信息 ret = avformat_find_stream_info(fmt_ctx, nullptr); if (ret < 0) { std::cerr << "avformat_find_stream_info error: " << av_err2str(ret) << std::endl; return 1; } // 找到视频流 int video_stream_index = -1; for (int i = 0; i < fmt_ctx->nb_streams; i++) { if (fmt_ctx->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_index = i; break; } } if (video_stream_index == -1) { std::cerr << "Cannot find video stream" << std::endl; return 1; } // 打开视频解码器 codec = avcodec_find_decoder(fmt_ctx->streams[video_stream_index]->codecpar->codec_id); if (!codec) { std::cerr << "Cannot find decoder for video stream" << std::endl; return 1; } codec_ctx = avcodec_alloc_context3(codec); if (!codec_ctx) { std::cerr << "Failed to allocate codec context" << std::endl; return 1; } ret = avcodec_parameters_to_context(codec_ctx, fmt_ctx->streams[video_stream_index]->codecpar); if (ret < 0) { std::cerr << "Failed to copy codec parameters to codec context" << std::endl; return 1; } ret = avcodec_open2(codec_ctx, codec, nullptr); if (ret < 0) { std::cerr << "Failed to open codec" << std::endl; return 1; } // 分配AVFrame并初始化 frame = av_frame_alloc(); if (!frame) { std::cerr << "Failed to allocate frame" << std::endl; return 1; } // 初始化pkt av_init_packet(&pkt); pkt.data = nullptr; pkt.size = 0; // 打开输出 AVFormatContext *out_fmt_ctx = nullptr; ret = avformat_alloc_output_context2(&out_fmt_ctx, nullptr, "rtsp", RTSP_URL); if (ret < 0) { std::cerr << "Failed to allocate output context" << std::endl; return 1; } AVStream *out_stream = avformat_new_stream(out_fmt_ctx, nullptr); if (!out_stream) { std::cerr << "Failed to create new stream" << std::endl; return 1; } AVCodecParameters *out_codecpar = out_stream->codecpar; avcodec_parameters_copy(out_codecpar, fmt_ctx->streams[video_stream_index]->codecpar); out_codecpar->codec_tag = 0; ret = avio_open(&out_fmt_ctx->pb, RTSP_URL, AVIO_FLAG_WRITE); if (ret < 0) { std::cerr << "Failed to open output" << std::endl; return 1; } // 写文件头 ret = avformat_write_header(out_fmt_ctx, nullptr); if (ret < 0) { std::cerr << "Failed to write header" << std::endl; return 1; } // 读取并解码数据 while (av_read_frame(fmt_ctx, &pkt) >= 0) { if (pkt.stream_index != video_stream_index) { av_packet_unref(&pkt); continue; } // 解码 ret = avcodec_send_packet(codec_ctx, &pkt); if (ret < 0) { std::cerr << "avcodec_send_packet error: " << av_err2str(ret) << std::endl; break; } while (ret >= 0) { ret = avcodec_receive_frame(codec_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { std::cerr << "avcodec_receive_frame error: " << av_err2str(ret) << std::endl; goto end; } // 转换像素格式 SwsContext *sws_ctx = sws_getContext(codec_ctx->width, codec_ctx->height, codec_ctx->pix_fmt, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_YUV420P, SWS_BILINEAR, nullptr, nullptr, nullptr); if (!sws_ctx) { std::cerr << "Failed to create SwsContext" << std::endl; goto end; } AVFrame *yuv_frame = av_frame_alloc(); if (!yuv_frame) { std::cerr << "Failed to allocate yuv_frame" << std::endl; goto end; } int dst_bufsize = av_image_get_buffer_size(AV_PIX_FMT_YUV420P, codec_ctx->width, codec_ctx->height, 1); uint8_t *dst_data[4] = {nullptr}; int dst_linesize[4] = {0}; ret = av_image_alloc(dst_data, dst_linesize, codec_ctx->width, codec_ctx->height, AV_PIX_FMT_YUV420P, 1); if (ret < 0) { std::cerr << "Failed to allocate image buffer" << std::endl; av_frame_free(&yuv_frame); goto end; } sws_scale(sws_ctx, frame->data, frame->linesize, 0, codec_ctx->height, yuv_frame->data, yuv_frame->linesize); yuv_frame->width = codec_ctx->width; yuv_frame->height = codec_ctx->height; yuv_frame->format = AV_PIX_FMT_YUV420P; // 编码 AVPacket out_pkt = {}; av_init_packet(&out_pkt); out_pkt.data = nullptr; out_pkt.size = 0; ret = avcodec_send_frame(codec_ctx, yuv_frame); if (ret < 0) { std::cerr << "avcodec_send_frame error: " << av_err2str(ret) << std::endl; av_packet_unref(&out_pkt); goto end; } while (ret >= 0) { ret = avcodec_receive_packet(codec_ctx, &out_pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { std::cerr << "avcodec_receive_packet error: " << av_err2str(ret) << std::endl; av_packet_unref(&out_pkt); goto end; } // 写入输出 out_pkt.stream_index = out_stream->index; av_packet_rescale_ts(&out_pkt, codec_ctx->time_base, out_stream->time_base); ret = av_interleaved_write_frame(out_fmt_ctx, &out_pkt); if (ret < 0) { std::cerr << "av_interleaved_write_frame error: " << av_err2str(ret) << std::endl; av_packet_unref(&out_pkt); goto end; } av_packet_unref(&out_pkt); } av_frame_free(&yuv_frame); } av_packet_unref(&pkt); } // 写文件尾 ret = av_write_trailer(out_fmt_ctx); if (ret < 0) { std::cerr << "Failed to write trailer" << std::endl; } end: if (codec_ctx) { avcodec_free_context(&codec_ctx); } if (fmt_ctx) { avformat_close_input(&fmt_ctx); } if (frame) { av_frame_free(&frame); } if (out_fmt_ctx) { avio_closep(&out_fmt_ctx->pb); avformat_free_context(out_fmt_ctx); } return 0; } 这个代码示例将从本地文件input.mp4中读取视频流,然后将视频流转换为YUV420P像素格式,接着使用AVCodec对YUV420P像素进行压缩编码,并将编码后的数据通过RTSP协议推送到远程服务器。需要注意的是,这个代码示例中使用的RTSP URL是rtsp://192.168.1.1/live,如果你要使用这个示例代码,请先将RTSP URL替换为你要推流的URL。另外,这个示例代码仅供参考,实际使用中还需要根据具体情况进行修改和优化。
以下是一个简单的 C++ 代码示例,用于使用 FFmpeg 获取 RTSP 视频流: c++ extern "C" { #include "libavformat/avformat.h" #include "libavcodec/avcodec.h" #include "libavutil/avutil.h" } int main(int argc, char* argv[]) { avformat_network_init(); // 初始化网络 AVFormatContext* pFormatContext = NULL; // 打开 RTSP 流 if (avformat_open_input(&pFormatContext, "rtsp://xxx.xxx.xxx.xxx:xxxx", NULL, NULL) != 0) { printf("打开 RTSP 流失败!\n"); return -1; } printf("打开 RTSP 流成功!\n"); // 查找 RTSP 流信息 if (avformat_find_stream_info(pFormatContext, NULL) < 0) { printf("查找 RTSP 流信息失败!\n"); return -1; } printf("查找 RTSP 流信息成功!\n"); // 找到视频流 int videoStream = -1; for (int i = 0; i < pFormatContext->nb_streams; i++) { if (pFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { videoStream = i; break; } } if (videoStream == -1) { printf("找不到视频流!\n"); return -1; } printf("找到视频流!\n"); // 获取解码器 AVCodecParameters* pCodecParameters = pFormatContext->streams[videoStream]->codecpar; AVCodec* pCodec = avcodec_find_decoder(pCodecParameters->codec_id); if (pCodec == NULL) { printf("找不到解码器!\n"); return -1; } printf("找到解码器!\n"); // 创建解码器上下文 AVCodecContext* pCodecContext = avcodec_alloc_context3(pCodec); if (avcodec_parameters_to_context(pCodecContext, pCodecParameters) != 0) { printf("创建解码器上下文失败!\n"); return -1; } // 打开解码器 if (avcodec_open2(pCodecContext, pCodec, NULL) < 0) { printf("打开解码器失败!\n"); return -1; } printf("打开解码器成功!\n"); // 创建 AVFrame AVFrame* pFrame = av_frame_alloc(); // 创建 AVPacket AVPacket* pPacket = av_packet_alloc(); // 读取视频帧 int ret = 0; while (av_read_frame(pFormatContext, pPacket) >= 0) { // 如果不是视频流,跳过 if (pPacket->stream_index != videoStream) { av_packet_unref(pPacket); continue; } // 解码视频帧 ret = avcodec_send_packet(pCodecContext, pPacket); if (ret < 0) { printf("解码视频帧失败!\n"); break; } while (ret >= 0) { ret = avcodec_receive_frame(pCodecContext, pFrame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { printf("解码视频帧失败!\n"); break; } // 处理视频帧 printf("处理视频帧:%lld\n", pFrame->pts); } av_packet_unref(pPacket); } // 释放资源 av_frame_free(&pFrame); av_packet_free(&pPacket); avcodec_close(pCodecContext); avcodec_free_context(&pCodecContext); avformat_close_input(&pFormatContext); avformat_free_context(pFormatContext); avformat_network_deinit(); return 0; } 在代码中,我们首先使用 avformat_open_input() 函数打开 RTSP 流,并使用 avformat_find_stream_info() 函数查找流信息。接着,我们找到视频流并获取解码器。然后,我们创建解码器上下文并打开解码器。最后,我们使用 av_read_frame() 函数读取视频帧,并使用解码器解码每一帧。在处理完视频帧后,我们释放资源,关闭解码器和输入流。

最新推荐

基于MATLAB下的appdesigner简单的黑体辐射虚拟仿真实验源码+项目说明.zip

【资源说明】 1、该资源包括项目的全部源码,下载可以直接使用! 2、本项目适合作为计算机、数学、电子信息等专业的课程设计、期末大作业和毕设项目,作为参考资料学习借鉴。 3、本资源作为“参考资料”如果需要实现其他功能,需要能看懂代码,并且热爱钻研,自行调试。 基于MATLAB下的appdesigner简单的黑体辐射虚拟仿真实验源码+项目说明.zip

day13-节后复习1.zip

day13-节后复习1.zip

本安装包VSCode,运用于C语言继承编译环境,嵌入式开发,Linux学习

VSCodeUserSetup-x64-1.63.2 是Visual Studio Code(VS Code)的64位安装程序版本,具体版本号为1.63.2。VS Code是由Microsoft开发的一款免费、开源的代码编辑器,支持Windows、macOS和Linux操作系统。它具有简洁的界面、丰富的功能和强大的扩展生态系统,广泛应用于前端、后端、移动端和人工智能等领域的开发。 以下是关于VSCodeUserSetup-x64-1.63.2版本的简要介绍: 64位版本:表示此安装程序适用于64位操作系统,可以充分利用系统资源,提高软件性能。 版本号:1.63.2表示该版本为VS Code的最新版本。版本号通常由三个部分组成,分别代表主版本号、次版本号和修订号。主版本号表示重大更新,次版本号表示功能更新,修订号表示修复bug和其他小更新。 安装程序:VSCodeUserSetup-x64-1.63.2是一个安装程序,用户可以通过它将VS Code安装到自己的电脑上。安装过程中,用户可以自定义安装路径、选择需要安装的组件等。 Visual Studio Code功能:VS Code具有

大学生创客平台代码 java大学生创客平台代码

大学生创客平台代码 java大学生创客平台代码 基于SSM的大学生创客平台代码 1、大学生创客平台的技术栈、环境、工具、软件: ① 系统环境:Windows/Mac ② 开发语言:Java ③ 框架:SSM ④ 架构:B/S、MVC ⑤ 开发环境:IDEA、JDK、Maven、Mysql ⑥ JDK版本:JDK1.8 ⑦ Maven包:Maven3.6 ⑧ 数据库:mysql 5.7 ⑨ 服务平台:Tomcat 8.0/9.0 ⑩ 数据库工具:SQLyog/Navicat ⑪ 开发软件:eclipse/myeclipse/idea ⑫ 浏览器:谷歌浏览器/微软edge/火狐 ⑬ 技术栈:Java、Mysql、Maven、SSM、Mybatis、Ajax、Vue等 2、适用人群:计算机,电子信息工程等专业的学习者等, 高分毕业设计项目,也可作为课程设计和期末大作业。本资源仅是代码的压缩包,该代码适合毕业设计、课程设计作业,所有源码均经过严格测试,可以放心下载使用。有任何使用问题欢迎随时与博主沟通,第一时间进行解答! 3、解压说明:本资源需要电脑端使用WinRAR、7zip、Ba

Unity答题系统案例

Unity答题系统案例,可适配单选或多选,通过读取题库中的存储的十进制数,将十进制数转化为二进制,然后对照ASCII码表来匹配正确答案

输入输出方法及常用的接口电路资料PPT学习教案.pptx

输入输出方法及常用的接口电路资料PPT学习教案.pptx

管理建模和仿真的文件

管理Boualem Benatallah引用此版本:布阿利姆·贝纳塔拉。管理建模和仿真。约瑟夫-傅立叶大学-格勒诺布尔第一大学,1996年。法语。NNT:电话:00345357HAL ID:电话:00345357https://theses.hal.science/tel-003453572008年12月9日提交HAL是一个多学科的开放存取档案馆,用于存放和传播科学研究论文,无论它们是否被公开。论文可以来自法国或国外的教学和研究机构,也可以来自公共或私人研究中心。L’archive ouverte pluridisciplinaire

Office 365常规运维操作简介

# 1. Office 365概述 ## 1.1 Office 365简介 Office 365是由微软提供的云端应用服务,为用户提供办公软件和生产力工具的订阅服务。用户可以通过互联网在任何设备上使用Office应用程序,并享受文件存储、邮件服务、在线会议等功能。 ## 1.2 Office 365的优势 - **灵活性**:用户可以根据实际需求选择不同的订阅计划,灵活扩展或缩减服务。 - **便捷性**:无需安装繁琐的软件,随时随地通过互联网访问Office应用程序和文件。 - **协作性**:多人可同时编辑文档、实时共享文件,提高团队协作效率。 - **安全性**:微软提供安全可靠

如何查看linux上安装的mysql的账号和密码

你可以通过以下步骤查看 Linux 上安装的 MySQL 的账号和密码: 1. 进入 MySQL 安装目录,一般是 /usr/local/mysql/bin。 2. 使用以下命令登录 MySQL: ``` ./mysql -u root -p ``` 其中,-u 表示要使用的用户名,这里使用的是 root;-p 表示需要输入密码才能登录。 3. 输入密码并登录。 4. 进入 MySQL 的信息库(mysql): ``` use mysql; ``` 5. 查看 MySQL 中的用户表(user): ``` se

最新电力电容器及其配套设备行业安全生产设备设施及隐患排查治理.docx

2021年 各行业安全生产教育培训