1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
/**
* @file
* audio encoding with libavcodec API example.
*
* @example encode_audio.c
*/
avcodec_find_encoder();//查找一个编码器encodec
avcodec_alloc_contex3();//根据编码器 申请一个编码上下文ctx
ctx->bit_rate;
ctx->sample_fmt;//根据encodec->sample_fmts查看是否支持
ctx->sample_rate;//根据encodec->supported_samplerates找一个最适合的
ctx->channel_layout;//根据const uint64_t *p=encodec->channel_layouts av_get_channel_layout_nb_channels(*p)找最大的通道
ctx->channels;//av_get_channel_layout_nb_channels(ctx->channel_layout)
avcodec_open2();//打开编码器与上下文绑定
av_packet_alloc();//分配并初始化一个pkt
av_frame_alloc();//分配并初始化一个frame
frame->nb_samples=ctx->frame_size;
frame->format=ctx->ctx->sample_fmt;
frame->channel_layout=ctx->channel_layout;
av_frame_get_buffer();//为frame分配buff空间
av_frame_make_writable();//确定帧是可写的


/ *
以每秒110Hz增加频率
tincr = 2 * M_PI * 110.0 / c-> sample_rate;
tincr2 = 2 * M_PI * 110.0 / c-> sample_rate / c-> sample_rate;
填充一段正弦波
*/
t = 0;
tincr = 2 * M_PI * 440.0 / ctx->sample_rate;
for (i = 0; i < 200; i++) {
ret = av_frame_make_writable(frame);
if (ret < 0)
exit(1);
samples = (uint16_t*)frame->data[0];
for (j = 0; j < c->frame_size; j++) {
samples[2 * j] = (int)(sin(t) * 10000);
for (k = 1; k < c->channels; k++)
samples[2 * j + k] = samples[2 * j];
t += tincr;
}
encode(ctx, frame, pkt, f);//avcodec_send_frame avcodec_receive_packet av_packet_unref
}
encode(ctx, NULL, pkt, f);

av_frame_free();//释放fream
av_packet_free();//释放pkt
avcodec_free_contex();//释放编码上下文
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
/**
* @file
* video encoding with libavcodec API example
*
* @example encode_video.c
*/
avcodec_find_encoder_by_name();//根据名字查找编码器encodec
avcodec_alloc_context3();//根据编码器 申请编码上下文ctx
av_packet_alloc();//分配pkt
ctx->bit_rate;
ctx->width;
ctx->height;
ctx->time_base;//AVRational{1,25} fps25
ctx->framerate;//AVRational{25,1}
ctx->gop_size;//多久一个关键帧
ctx->max_b_frames;//最多b帧
ctx->pix_fmt;//帧格式
if (codec->id == AV_CODEC_ID_H264) av_opt_set(ctx->priv_data, "preset", "slow", 0);
/*AVOption除了可以对常用的结构体AVFormatContext、AVCodecContext等进行设置之外,还可以对它们的私有数据priv_data进行赋值。这些字段里面通常存储了各种编码器特有的结构体。如使用libx264进行编码的时候,通过AVCodecContext的priv_data字段可以对X264Context(libavcodec\libx264.c)结构体中的变量进行赋值,设置preset、profile等*/
avcodec_open2();//打开编码器与上下文绑定
av_frame_alloc();//初始化frame
frame->format=ctx->pix_fmt;
frame->width=ctx->width;
frame->height=ctx->height;
av_frame_get_buffer();//为frame申请内部空间
av_frame_make_writable();//确定帧是可写的

填满frame->data;
encodec();

avcodec_free_context();
av_frame_free();
av_packet_free();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,FILE *outfile){
int ret;
/* send the frame to the encoder */
if (frame)
printf("Send frame %3"PRId64"\n", frame->pts);

ret = avcodec_send_frame(enc_ctx, frame);
if (ret < 0) {
fprintf(stderr, "Error sending a frame for encoding\n");
exit(1);
}

while (ret >= 0) {
ret = avcodec_receive_packet(enc_ctx, pkt);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0) {
fprintf(stderr, "Error during encoding\n");
exit(1);
}

printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
fwrite(pkt->data, 1, pkt->size, outfile);
av_packet_unref(pkt);
}
}