av_interleaved_write_frame 编码h264, 保存为ts格式
时间: 2023-08-25 20:04:49 浏览: 327
利用ffmpeg从USB摄像头获取视频并保存为H264的TS流的C语言源代码
你可以使用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;
}
```
需要注意的是,这只是一个简单的示例代码,实际使用时需要根据具体的需求进行修改和完善。
阅读全文