本篇文章写一个视频复用器。输入一个pcm文件和一个yuv文件。pcm文件格式是f32le,单声道,采样率是48000。yuv文件格式是yuv420p,848x400。
读入两个文件,分别进行音频和视频编码,然后mux成目标文件,比如xxx.mp4。
代码中选择了编码2声道的音频,由于输入的pcm是单声道,所以代码中简单复制了pcm的数据到frame->data[1]中。
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libswscale/swscale.h>
#include <libavutil/imgutils.h>
#include <libavutil/samplefmt.h>
#include <libavutil/timestamp.h>
typedef struct OutputStream {
AVStream *st;
AVCodecContext *enc_ctx;
/* 下一帧pts */
int64_t next_pts;
AVFrame *frame;
} OutputStream;
static AVFormatContext *ofmt_ctx;
static OutputStream video_st = {0}, audio_st = {0};
static FILE *in_file_v, *in_file_a;
static void log_packet(const AVPacket *pkt)
{
AVRational *time_base = &ofmt_ctx->streams[pkt->stream_index]->time_base;
printf("pts:%s pts_time:%s dts:%s dts_time:%s duration:%s duration_time:%s stream_index:%d\n",
av_ts2str(pkt->pts), av_ts2timestr(pkt->pts, time_base),
av_ts2str(pkt->dts), av_ts2timestr(pkt->dts, time_base),
av_ts2str(pkt->duration), av_ts2timestr(pkt->duration, time_base),
pkt->stream_index);
}
static void setup_video_stream()
{
int ret;
AVCodec *codec = avcodec_find_encoder(AV_CODEC_ID_H264);
if (!codec) {
printf("could not find %s encoder\n", avcodec_get_name(AV_CODEC_ID_H264));
exit(1);
}
//创建流
video_st.st = avformat_new_stream(ofmt_ctx, NULL);
if (!video_st.st) {
printf("avformat_new_stream fail \n");
exit(1);
}
//打开codec context
video_st.enc_ctx = avcodec_alloc_context3(codec);
if (!video_st.enc_ctx) {
printf("avcodec_alloc_context3 fail \n");
exit(1);
}
//设置编码参数
video_st.enc_ctx->bit_rate = 400000;
video_st.enc_ctx->width = 848;
video_st.enc_ctx->height = 480;
video_st.enc_ctx->pix_fmt = AV_PIX_FMT_YUV420P;
video_st.st->time_base = (AVRational){1, 25};
video_st.enc_ctx->time_base = video_st.st->time_base;
video_st.enc_ctx->gop_size = 12;
video_st.enc_ctx->max