avformat_open_input 设置timeout 出现-10049 error 不设置timeout没问题 是什么原因
时间: 2024-05-23 13:13:06 浏览: 179
avformat_open_input是FFmpeg用来打开一个输入媒体文件的函数,而timeout是设置超时时间的参数。出现-10049 error通常是因为网络连接超时导致的,这个错误码对应的是WSAEADDRNOTAVAIL,即“无效地址”。如果你设置了timeout,那么当网络连接超时时,avformat_open_input会返回这个错误码。如果你没有设置timeout,avformat_open_input会一直等待网络连接成功,直到超时时间达到系统默认值。所以,如果你没有设置timeout,那么程序在等待网络连接成功时就不会出现错误。
相关问题
./ffmpeg_g -re -i /home/tsdl/Downloads/test0524.mp4 -vcodec libx264 -profile:v baseline -r 25 -g 50 -f rtc "http://192.168.114.34:1985/rtc/v1/whip/?app=live&stream=livestream"生成C代码示例
以下是使用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
```
av_interleaved_write_frame 编码h264, 保存为ts格式
你可以使用FFmpeg库中的avformat和avcodec模块来实现将h264编码的视频保存为ts格式的功能。下面是一个简单的代码示例:
```c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libavformat/avformat.h>
#include <libavcodec/avcodec.h>
int main(int argc, char *argv[]) {
const char *input_file = "input.h264";
const char *output_file = "output.ts";
AVFormatContext *in_ctx = NULL, *out_ctx = NULL;
AVCodec *codec = NULL;
AVCodecContext *codec_ctx = NULL;
AVPacket packet;
int ret = 0;
// 打开输入文件
if ((ret = avformat_open_input(&in_ctx, input_file, NULL, NULL)) < 0) {
fprintf(stderr, "Error opening input file: %s\n", av_err2str(ret));
goto end;
}
// 查找视频流
if ((ret = avformat_find_stream_info(in_ctx, NULL)) < 0) {
fprintf(stderr, "Error finding stream information: %s\n", av_err2str(ret));
goto end;
}
// 打开输出文件
if ((ret = avformat_alloc_output_context2(&out_ctx, NULL, NULL, output_file)) < 0) {
fprintf(stderr, "Error opening output file: %s\n", av_err2str(ret));
goto end;
}
// 添加视频流
codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "H.264 codec not found\n");
goto end;
}
codec_ctx = avcodec_alloc_context3(codec);
codec_ctx->width = in_ctx->streams[0]->codecpar->width;
codec_ctx->height = in_ctx->streams[0]->codecpar->height;
codec_ctx->pix_fmt = in_ctx->streams[0]->codecpar->format;
codec_ctx->time_base = in_ctx->streams[0]->time_base;
if ((ret = avcodec_open2(codec_ctx, codec, NULL)) < 0) {
fprintf(stderr, "Error opening codec: %s\n", av_err2str(ret));
goto end;
}
AVStream *out_stream = avformat_new_stream(out_ctx, codec);
if (!out_stream) {
fprintf(stderr, "Error creating output stream\n");
goto end;
}
out_stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO;
out_stream->codecpar->codec_id = codec->id;
out_stream->codecpar->width = codec_ctx->width;
out_stream->codecpar->height = codec_ctx->height;
out_stream->codecpar->format = codec_ctx->pix_fmt;
out_stream->codecpar->bit_rate = codec_ctx->bit_rate;
out_stream->codecpar->extradata = codec_ctx->extradata;
out_stream->codecpar->extradata_size = codec_ctx->extradata_size;
avcodec_parameters_to_context(out_stream->codec, out_stream->codecpar);
// 打开输出文件
if (!(out_ctx->oformat->flags & AVFMT_NOFILE)) {
if ((ret = avio_open(&out_ctx->pb, output_file, AVIO_FLAG_WRITE)) < 0) {
fprintf(stderr, "Error opening output file: %s\n", av_err2str(ret));
goto end;
}
}
// 写文件头
if ((ret = avformat_write_header(out_ctx, NULL)) < 0) {
fprintf(stderr, "Error writing header: %s\n", av_err2str(ret));
goto end;
}
// 读取并编码每一帧
while (1) {
AVStream *in_stream = in_ctx->streams[0];
if ((ret = av_read_frame(in_ctx, &packet)) < 0) {
break;
}
if (packet.stream_index != 0) {
av_packet_unref(&packet);
continue;
}
av_packet_rescale_ts(&packet, in_stream->time_base, codec_ctx->time_base);
if ((ret = avcodec_send_packet(codec_ctx, &packet)) < 0) {
fprintf(stderr, "Error sending packet to encoder: %s\n", av_err2str(ret));
av_packet_unref(&packet);
break;
}
while (1) {
AVFrame *frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Error allocating frame\n");
ret = AVERROR(ENOMEM);
goto end;
}
ret = avcodec_receive_frame(codec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
av_frame_free(&frame);
break;
} else if (ret < 0) {
fprintf(stderr, "Error receiving frame from encoder: %s\n", av_err2str(ret));
av_frame_free(&frame);
goto end;
}
frame->pts = frame->best_effort_timestamp;
AVPacket out_packet;
av_init_packet(&out_packet);
out_packet.data = NULL;
out_packet.size = 0;
if ((ret = avcodec_send_frame(codec_ctx, frame)) < 0) {
fprintf(stderr, "Error sending frame to encoder: %s\n", av_err2str(ret));
av_frame_free(&frame);
goto end;
}
while (1) {
ret = avcodec_receive_packet(codec_ctx, &out_packet);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
av_packet_unref(&out_packet);
break;
} else if (ret < 0) {
fprintf(stderr, "Error receiving packet from encoder: %s\n", av_err2str(ret));
av_packet_unref(&out_packet);
goto end;
}
out_packet.stream_index = 0;
av_packet_rescale_ts(&out_packet, codec_ctx->time_base, out_stream->time_base);
if ((ret = av_interleaved_write_frame(out_ctx, &out_packet)) < 0) {
fprintf(stderr, "Error writing packet to output file: %s\n", av_err2str(ret));
av_packet_unref(&out_packet);
goto end;
}
av_packet_unref(&out_packet);
}
av_frame_free(&frame);
}
av_packet_unref(&packet);
}
// 写文件尾
if ((ret = av_write_trailer(out_ctx)) < 0) {
fprintf(stderr, "Error writing trailer: %s\n", av_err2str(ret));
goto end;
}
end:
if (codec_ctx) {
avcodec_free_context(&codec_ctx);
}
if (in_ctx) {
avformat_close_input(&in_ctx);
}
if (out_ctx) {
if (!(out_ctx->oformat->flags & AVFMT_NOFILE)) {
avio_closep(&out_ctx->pb);
}
avformat_free_context(out_ctx);
}
return ret;
}
```
需要注意的是,这只是一个简单的示例代码,实际使用时需要根据具体的需求进行修改和完善。
阅读全文