metaRTC新增whip/whep支持

概述

webrtc流媒体部分标准化了,但信令部分缺乏标准,WHIP和WHEP协议的推出,补全了webrtc标准最后的短板。
metaRTC6.0最新版本新增whip和whep协议的支持,使metaRTC可以和Janus/Mediasoup/Freeswitch等SFU和MCU通信。
WHIP: WebRTC HTTP Ingestion Protocol
WHEP: WebRTC HTTP Egress Protocol

whip/whep支持

#define Yang_Server_Srs 0
#define Yang_Server_Zlm 1
#define Yang_Server_P2p 7
#define Yang_Server_Whip_Whep 9
  //Yang_Server_Srs/Yang_Server_Zlm/Yang_Server_P2p/Yang_Server_Whip_Whep
    m_context->avinfo.sys.mediaServer=Yang_Server_Whip_Whep;
    m_context->avinfo.rtc.rtcSocketProtocol=Yang_Socket_Protocol_Udp;

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是使用FFmpeg库生成相应的C代码示例,可以实现将本地视频文件实时推流到指定的RTMP服务器: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <unistd.h> #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libavutil/avutil.h> int main(int argc, char **argv) { AVFormatContext *fmt_ctx = NULL; AVCodecContext *video_enc_ctx = NULL; AVCodec *video_enc = NULL; AVStream *video_stream = NULL; AVOutputFormat *out_fmt = NULL; AVIOContext *out_io_ctx = NULL; AVFormatContext *out_fmt_ctx = NULL; AVPacket pkt; int ret; char *in_filename = "/home/tsdl/Downloads/test0524.mp4"; char *out_filename = "http://192.168.114.34:1985/rtc/v1/whip/?app=live&stream=livestream"; // 注册所有的编解码器、封装器和协议 av_register_all(); avformat_network_init(); // 打开输入文件 if ((ret = avformat_open_input(&fmt_ctx, in_filename, NULL, NULL)) < 0) { fprintf(stderr, "Could not open input file '%s'\n", in_filename); goto end; } // 查找流信息 if ((ret = avformat_find_stream_info(fmt_ctx, NULL)) < 0) { fprintf(stderr, "Could not find stream information\n"); goto end; } // 选择视频流 int video_stream_index = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, &video_enc, 0); if (video_stream_index < 0) { fprintf(stderr, "Could not find video stream in input file '%s'\n", in_filename); goto end; } // 打开视频解码器 video_enc_ctx = avcodec_alloc_context3(video_enc); if (!video_enc_ctx) { fprintf(stderr, "Could not allocate video encoder context\n"); goto end; } if ((ret = avcodec_parameters_to_context(video_enc_ctx, fmt_ctx->streams[video_stream_index]->codecpar)) < 0) { fprintf(stderr, "Could not copy video codec parameters to encoder context\n"); goto end; } if ((ret = avcodec_open2(video_enc_ctx, video_enc, NULL)) < 0) { fprintf(stderr, "Could not open video encoder\n"); goto end; } // 创建输出格式上下文 if ((ret = avformat_alloc_output_context2(&out_fmt_ctx, NULL, "rtmp", out_filename)) < 0) { fprintf(stderr, "Could not allocate output format context\n"); goto end; } // 创建输出流 video_stream = avformat_new_stream(out_fmt_ctx, NULL); if (!video_stream) { fprintf(stderr, "Could not allocate video output stream\n"); goto end; } // 复制编解码器参数 if ((ret = avcodec_parameters_copy(video_stream->codecpar, fmt_ctx->streams[video_stream_index]->codecpar)) < 0) { fprintf(stderr, "Could not copy video codec parameters\n"); goto end; } // 设置输出流时间基准 video_stream->time_base = video_enc_ctx->time_base; // 打开输出IO上下文 if ((ret = avio_open2(&out_io_ctx, out_filename, AVIO_FLAG_WRITE, NULL, NULL)) < 0) { fprintf(stderr, "Could not open output url '%s'\n", out_filename); goto end; } out_fmt_ctx->pb = out_io_ctx; // 写入输出格式头部 if ((ret = avformat_write_header(out_fmt_ctx, NULL)) < 0) { fprintf(stderr, "Could not write output format header\n"); goto end; } // 初始化AVPacket av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; // 读取并编码视频帧 while (1) { AVStream *in_stream, *out_stream; AVFrame *frame = av_frame_alloc(); if ((ret = av_read_frame(fmt_ctx, &pkt)) < 0) { break; } if (pkt.stream_index == video_stream_index) { avcodec_send_packet(video_enc_ctx, &pkt); while (ret >= 0) { ret = avcodec_receive_frame(video_enc_ctx, frame); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { fprintf(stderr, "Error while receiving a video frame from the encoder\n"); goto end; } // 编码并发送视频帧 av_packet_unref(&pkt); av_init_packet(&pkt); ret = avcodec_send_frame(video_enc_ctx, frame); if (ret < 0) { fprintf(stderr, "Error while sending a video frame to the encoder\n"); goto end; } while (ret >= 0) { ret = avcodec_receive_packet(video_enc_ctx, &pkt); if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) { break; } else if (ret < 0) { fprintf(stderr, "Error while receiving a video packet from the encoder\n"); goto end; } // 发送视频包到输出流 av_packet_rescale_ts(&pkt, video_enc_ctx->time_base, video_stream->time_base); pkt.stream_index = video_stream->index; av_interleaved_write_frame(out_fmt_ctx, &pkt); av_packet_unref(&pkt); av_init_packet(&pkt); } } av_frame_unref(frame); } av_packet_unref(&pkt); } // 写入输出格式尾部 av_write_trailer(out_fmt_ctx); end: if (video_enc_ctx) { avcodec_free_context(&video_enc_ctx); } if (fmt_ctx) { avformat_close_input(&fmt_ctx); } if (out_fmt_ctx) { avio_closep(&out_fmt_ctx->pb); avformat_free_context(out_fmt_ctx); } if (out_io_ctx) { av_freep(&out_io_ctx->buffer); av_free(out_io_ctx); } if (ret < 0) { fprintf(stderr, "Error occurred: %s\n", av_err2str(ret)); return 1; } return 0; } ``` 注意需要将代码中的输入文件路径和输出URL替换为实际的路径和URL。另外,还需要在编译时链接FFmpeg库,例如使用gcc编译器编译上述代码的命令为: ``` gcc -o ffmpeg_push_stream ffmpeg_push_stream.c -lavformat -lavcodec -lavutil -lm ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

metaRTC

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值