音视频编码流程

1. 获取编码器AVCodec


2. 分配编码上下文AVCodecContext


3. 设置编码参数


3.1 音频

    ctx->codec_id = AV_CODEC_ID_AAC;
    ctx->codec_type = AV_MEDIA_TYPE_AUDIO;
    ctx->bit_rate = 128 * 1024;
    ctx->channel_layout = AV_CH_LAYOUT_STEREO;
    ctx->sample_rate = 48000;
    ctx->channels = av_get_channel_layout_nb_channels(ctx->channel_layout);
    ctx->profile  = FF_PROFILE_AAC_LOW;
    ctx->sample_fmt = sample_fmt;
    ctx->flags = AV_CODEC_FLAG_GLOBAL_HEADER;

3.2 视频

ctx->width = 1280;
ctx->height = 720;
ctx->time_base = (AVRation){1, 25};
ctx->framerate = (AVRation){25, 1};
ctx->gop_size = 25;
ctx->max_b_frames = 0;
ctx->pix_fmt = AV_PIX_FMT_YUV420P;
ctx->bit_rate = 3000000;

4. 关联编码器与编码上下文


5. 创建frame与packet


6. 初始化frame参数,编码格式


6.1音频参数

    frame->nb_samples = ctx->frame_size;
    frame->format = ctx->sample_fmt;
    frame->channel_layout = ctx->channel_layout;
    frame->channels = av_get_channel_layout_nb_channels(frame-	>channel_layout);

6.2 视频参数

   frame->foramt = ctx->pix_fmt;
   frame->width  = ctx->width;
   frame->height = ctx->height;

7. 为frame中buffer分配内存


8. 循环读取数据进行编码


8.1. 音频逐帧读取pcm数据

  1. 循环从文件中读取一帧数据(编码一个frame)
    • bytes = av_get_bytes_per_sample() * channles * nb_samples
  2. 设置采样帧可写属性
  3. 将读取到的数据bytes写入到frame中
    • av_samples_fill_arrays
  4. 更新pts:以样本数量为time_base
    • pts += frame->nb_samples
  5. 编码frame为packet
    • av_send_frame
    • av_receive_packet
    • 判断需要增加adts帧头add_adts_header
    • 转储packet

8.2 . 视频逐帧读取yuv数据

  1. 循环从yuv文件中读取一帧数据(编码一个frame)
    • bytes = av_image_get_buffer_size();
  2. 设置视频帧数据可写属性
    • av_frame_make_writable
  3. 将读取到的yuv数据填充到frame中
    • av_image_fill_arrays
  4. 更新pts:以framerate为单位
    • frame->pts += 40
  5. 编码frame为packet
    • avcodec_send_frame
    • avcodec_receive_packet
  • 写编码文件

9. 冲刷编码数据队列


10. 释放资源


av_frame_free
av_packet_free
avcodec_free_context
posted @ 2021-12-09 23:39  flxx  阅读(301)  评论(0编辑  收藏  举报