一、基础概念
FFmpeg是一组开源的流媒体处理工具(包括编解码器、混流器、推流器等),由C语言写成,可跨平台运行在Windows、Linux等操作系统上。
推流是将音视频数据通过网络传输到服务器的过程,常用于直播、视频会议等场景。
在使用FFmpeg推流之前需要先了解以下概念:
1、编码器:将音视频数据从原始格式编码为压缩格式
2、解码器:将压缩格式的音视频数据解码为原始格式
3、封装格式:将音视频数据流、音频码率、摄像头分辨率等元数据封装到一个完整的包中
4、协议:音视频数据在传输过程中需要使用通信协议,如RTMP、RTSP等
二、推流基本操作
FFmpeg推流的基本操作包括打开输入输出、获取编码解码器、设置参数、读取数据、编码数据、推送数据等步骤。下面是一个简单的推流代码实例:
AVFormatContext *in_fmt_ctx, *out_fmt_ctx; avformat_open_input(&in_fmt_ctx, "input.flv", NULL, NULL); avformat_find_stream_info(in_fmt_ctx, NULL); int video_stream_index = av_find_best_stream(in_fmt_ctx, AVMEDIA_TYPE_VIDEO, -1, -1, NULL, 0); AVCodecParameters *codecpar = in_fmt_ctx->streams[video_stream_index]->codecpar; AVCodec *codec = avcodec_find_decoder(codecpar->codec_id); AVCodecContext *codec_ctx = avcodec_alloc_context3(codec); avcodec_parameters_to_context(codec_ctx, codecpar); avcodec_open2(codec_ctx, codec, NULL); avformat_alloc_output_context2(&out_fmt_ctx, NULL, "flv", "rtmp://server/live/stream"); AVStream *out_stream = avformat_new_stream(out_fmt_ctx, NULL); AVCodecParameters *out_par = avcodec_parameters_alloc(); avcodec_parameters_copy(out_par, codecpar); out_stream->codecpar = out_par; avformat_write_header(out_fmt_ctx, NULL); AVPacket pkt; av_init_packet(&pkt); pkt.data = NULL; pkt.size = 0; while (av_read_frame(in_fmt_ctx, &pkt) >= 0) { if (pkt.stream_index == video_stream_index) { AVFrame *frame = av_frame_alloc(); AVFrame *out_frame = av_frame_alloc(); avcodec_send_packet(codec_ctx, &pkt); while (avcodec_receive_frame(codec_ctx, frame) == 0) { // 编码数据 // 推送数据 av_packet_unref(&pkt); break; } av_frame_free(&frame); av_frame_free(&out_frame); } } av_write_trailer(out_fmt_ctx); avformat_close_input(&in_fmt_ctx); avformat_free_context(out_fmt_ctx);
三、设置音视频参数
在推流过程中,需要设置音视频的参数,如帧率、码率、分辨率等。下面是设置视频参数的示例代码:
AVCodecContext *codec_ctx = avcodec_alloc_context3(codec); codec_ctx->bit_rate = 400000; codec_ctx->width = 640; codec_ctx->height = 480; codec_ctx->time_base = (AVRational){1, 25}; AVDictionary *opts = NULL; av_dict_set(&opts, "profile", "baseline", 0); av_dict_set(&opts, "preset", "superfast", 0); avcodec_open2(codec_ctx, codec, &opts);
四、使用GPU加速
使用GPU加速可以提高编码速度和推流效率。FFmpeg支持多种GPU加速器,包括Nvidia的CUDA、Intel的Quick Sync Video等。下面是使用CUDA加速的示例代码:
AVCodec *codec = avcodec_find_encoder_by_name("h264_nvenc"); AVCodecContext *codec_ctx = avcodec_alloc_context3(codec); codec_ctx->pix_fmt = AV_PIX_FMT_CUDA; // 设置其他参数 AVDictionary *opts = NULL; av_dict_set(&opts, "gpu", "cuda", 0); av_dict_set(&opts, "profile", "high", 0); av_dict_set(&opts, "preset", "fast", 0); avcodec_open2(codec_ctx, codec, &opts);
五、实现直播功能
推流常用于直播场景,可以通过FFmpeg实现直播功能。以下是一个简单的直播示例代码:
AVDictionary *opts = NULL; av_dict_set(&opts, "listen", "1", 0); av_dict_set(&opts, "i", "rtmp://localhost/live/stream", 0); av_dict_set(&opts, "vcodec", "copy", 0); av_dict_set(&opts, "acodec", "aac", 0); av_dict_set(&opts, "f", "flv", 0); av_dict_set(&opts, "preset", "fast", 0); avformat_network_init(); AVOutputFormat *fmt = av_guess_format("flv", NULL, NULL); AVFormatContext *ctx = NULL; avformat_alloc_output_context2(&ctx, fmt, "flv", "rtmp://localhost/live/newstream"); avio_open2(&ctx->pb, "rtmp://localhost/live/newstream", AVIO_FLAG_WRITE, NULL, &opts); AVStream *out_stream = avformat_new_stream(ctx, NULL); AVStream *in_stream = avformat_new_stream(ctx, NULL); AVCodecParameters *in_par = avcodec_parameters_alloc(); AVCodecParameters *out_par = avcodec_parameters_alloc(); avcodec_parameters_from_context(in_par, in_fmt_ctx->streams[video_stream_index]->codec); avcodec_parameters_copy(out_par, in_par); out_stream->codecpar = out_par; avformat_write_header(ctx, NULL); while (1) { AVPacket packet; av_init_packet(&packet); if (av_read_frame(in_fmt_ctx, &packet) >= 0) { if (packet.stream_index == video_stream_index) { packet.stream_index = out_stream->index; } av_interleaved_write_frame(ctx, &packet); av_packet_unref(&packet); } else { break; } } av_write_trailer(ctx); avio_close(ctx->pb); avformat_free_context(ctx);
六、结论
本文从基础概念、推流基本操作、设置音视频参数、使用GPU加速、实现直播功能等多个方面对FFmpeg推流技术做了详细的阐述。通过实际代码示例,读者可以深入了解FFmpeg推流技术的实现原理和应用场景,进一步提升音视频编程技能。