返回
FFmpeg之new_video_stream添加视频输出流
前端
2024-01-30 07:38:23
FFmpeg简介
FFmpeg是一个开源的跨平台多媒体框架,可以处理各种各样的音频和视频格式。它可以用于视频编码、解码、转码、复用、解复用、流媒体等多种用途。FFmpeg支持多种协议,包括HTTP、FTP、RTSP、RTMP等。
new_video_stream()函数概述
new_video_stream()函数用于向一个输出媒体流添加一个新的视频流。该函数的流程相对来说比较简单,主要的逻辑如下:
- 调用new_output_stream()函数来创建OutputStream输出流。
- 调用avcodec_find_encoder()函数来查找一个合适的视频编码器。
- 调用avcodec_alloc_context3()函数来分配一个AVCodecContext结构体。
- 调用avcodec_parameters_to_context()函数将AVCodecParameters结构体中的参数复制到AVCodecContext结构体中。
- 调用avcodec_open2()函数来打开视频编码器。
- 调用av_new_stream()函数来创建一个新的视频流。
- 将视频编码器和视频流关联起来。
- 返回视频流的索引。
new_video_stream()函数语法
AVStream *avformat_new_video_stream(AVFormatContext *s, AVCodec *codec)
new_video_stream()函数参数
参数 | 类型 | 说明 |
---|---|---|
s | AVFormatContext * | 输出媒体流的上下文 |
codec | AVCodec * | 视频编码器 |
new_video_stream()函数返回值
如果成功,则返回视频流的索引;否则,返回NULL。
new_video_stream()函数示例
#include <libavformat/avformat.h>
int main() {
AVFormatContext *fmt_ctx = NULL;
AVStream *video_stream = NULL;
AVCodec *video_codec = NULL;
AVCodecContext *video_codec_ctx = NULL;
// 打开输入媒体文件
if (avformat_open_input(&fmt_ctx, "input.mp4", NULL, NULL) < 0) {
fprintf(stderr, "Could not open input file.\n");
return -1;
}
// 查找视频编码器
video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!video_codec) {
fprintf(stderr, "Could not find video encoder.\n");
return -1;
}
// 分配AVCodecContext结构体
video_codec_ctx = avcodec_alloc_context3(video_codec);
if (!video_codec_ctx) {
fprintf(stderr, "Could not allocate video codec context.\n");
return -1;
}
// 将AVCodecParameters结构体中的参数复制到AVCodecContext结构体中
if (avcodec_parameters_to_context(video_codec_ctx, fmt_ctx->streams[0]->codecpar) < 0) {
fprintf(stderr, "Could not copy codec parameters.\n");
return -1;
}
// 打开视频编码器
if (avcodec_open2(video_codec_ctx, video_codec, NULL) < 0) {
fprintf(stderr, "Could not open video encoder.\n");
return -1;
}
// 创建一个新的视频流
video_stream = avformat_new_video_stream(fmt_ctx, video_codec);
if (!video_stream) {
fprintf(stderr, "Could not create video stream.\n");
return -1;
}
// 将视频编码器和视频流关联起来
video_stream->codec = video_codec_ctx;
// 写入输出媒体文件
if (avformat_write_header(fmt_ctx, NULL) < 0) {
fprintf(stderr, "Could not write header.\n");
return -1;
}
// 写入视频数据
while (1) {
AVPacket pkt;
// 从输入媒体文件中读取一帧视频数据
if (av_read_frame(fmt_ctx, &pkt) < 0) {
break;
}
// 将视频数据编码成H.264格式
if (pkt.stream_index == 0) {
if (avcodec_send_frame(video_codec_ctx, &pkt) < 0) {
fprintf(stderr, "Could not send frame to encoder.\n");
return -1;
}
while (1) {
AVPacket enc_pkt;
// 从编码器中获取编码后的视频数据
if (avcodec_receive_packet(video_codec_ctx, &enc_pkt) < 0) {
break;
}
// 将编码后的视频数据写入输出媒体文件中
if (av_interleaved_write_frame(fmt_ctx, &enc_pkt) < 0) {
fprintf(stderr, "Could not write frame.\n");
return -1;
}
av_packet_unref(&enc_pkt);
}
}
av_packet_unref(&pkt);
}
// 写入输出媒体文件的尾部
if (av_write_trailer(fmt_ctx) < 0) {
fprintf(stderr, "Could not write trailer.\n");
return -1;
}
// 释放资源
avcodec_close(video_codec_ctx);
avformat_free_context(fmt_ctx);
return 0;
}
new_video_stream()函数应用场景
new_video_stream()函数可以用于多种场景,包括:
- 视频转码:将一种格式的视频转码成另一种格式的视频。
- 视频复用:将多个视频流复用成一个视频文件。
- 视频解复用:将一个视频文件解复用成多个视频流。
- 视频流媒体:将视频流传输到客户端进行播放。