av_find_best_stream
时间: 2023-07-11 12:56:40 浏览: 69
av_find_best_stream是一个使用FFmpeg库的函数调用,用于选择音视频文件中的最佳流进行解码。它会根据流的类型、编码格式、分辨率等因素进行评估,并返回最佳的流的索引值。
该函数有三个参数,第一个参数是指向AVFormatContext结构体的指针,第二个参数是指定流的类型,可以是AVMEDIA_TYPE_VIDEO、AVMEDIA_TYPE_AUDIO等,也可以是-1表示任意类型的流。第三个参数是指定相关流的索引值,一般为0。函数执行成功后,返回值为最佳流的索引值,如果没有找到适合的流,返回值为负数。
一般在调用av_find_best_stream函数之前,需要先调用avformat_find_stream_info函数来获取音视频文件的流信息,并将其存储到AVFormatContext结构体中。
相关问题
avformat_find_stream_info(pctx, NULL)
这是一个使用FFmpeg库的函数调用,用于获取音视频文件的流信息,并将其存储到AVFormatContext结构体中。其中,第一个参数是指向AVFormatContext结构体的指针,第二个参数用于指定流的选项,一般为NULL。如果函数执行成功,返回值为非负数,表示获取到的流的个数。如果函数执行失败,返回值为负数,表示获取流信息的过程中出现了错误。
这个函数调用之后,一般会接着调用av_find_best_stream函数来选择音视频流进行解码。
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;
}
```
需要注意的是,这只是一个简单的示例代码,实际使用时需要根据具体的需求进行修改和完善。