返回

FFmpeg 视频流编码流程:从小白到进阶

见解分享

图像编码:从 H.264 到 MP4

图像编码概述

视频编码是将原始视频帧压缩成更小文件大小的过程,从而减少传输和存储需求,同时保持视频质量。H.264 和 MP4 都是广泛使用的视频编码格式。H.264 是一种高度压缩的编解码器,而 MP4 是一种容器格式,通常包含 H.264 编码的视频流。

从图像到 H.264 的编码

准备阶段

  1. 使用 FFmpeg 打开图像文件。
  2. 检索视频流信息。
  3. 创建输出视频文件。
  4. 添加视频流并设置 H.264 编解码器。

编码阶段

  1. 初始化 H.264 编解码器。
  2. 分配编码帧缓冲区。
  3. 读取图像帧。
  4. 编码图像帧为 H.264 码流。
  5. 将编码帧写入输出视频文件。

结束阶段

  1. 释放 H.264 编解码器。
  2. 关闭输出视频文件。

从图像到 MP4 的编码

准备阶段

  1. 创建 MP4 容器。
  2. 添加视频流并设置 H.264 编解码器。
  3. 添加音频流(可选)。

编码阶段

  1. 编码视频流为 H.264 码流。
  2. 将编码后的 H.264 码流封装到 MP4 容器。
  3. 编码音频流并封装到 MP4 容器(如果需要)。

结束阶段

  1. 关闭 MP4 容器。

代码示例(C++)

// 编码图像为 H.264

int encode_image_to_h264(const char* input_file, const char* output_file) {
  AVFormatContext* input_context = avformat_alloc_context();
  avformat_open_input(&input_context, input_file, NULL, NULL);

  AVFormatContext* output_context = avformat_alloc_context();
  avformat_alloc_output_context2(&output_context, NULL, "mp4", output_file);

  AVStream* video_stream = avformat_new_stream(output_context, NULL);
  AVCodec* video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
  avcodec_open2(video_codec, NULL, NULL);

  AVFrame* frame = av_frame_alloc();
  AVPacket pkt;

  while (av_read_frame(input_context, &pkt) >= 0) {
    if (pkt.stream_index == video_stream->index) {
      avcodec_encode_video2(video_codec, &pkt, frame, &got_packet);
      if (got_packet) {
        av_interleaved_write_frame(output_context, &pkt);
        av_packet_unref(&pkt);
      }
    }
  }

  avcodec_close(video_codec);
  avformat_close_input(&input_context);
  avformat_free_context(output_context);

  return 0;
}

// 编码图像为 MP4

int encode_image_to_mp4(const char* input_file, const char* output_file) {
  AVFormatContext* input_context = avformat_alloc_context();
  avformat_open_input(&input_context, input_file, NULL, NULL);

  AVFormatContext* output_context = avformat_alloc_context();
  avformat_alloc_output_context2(&output_context, NULL, "mp4", output_file);

  AVStream* video_stream = avformat_new_stream(output_context, NULL);
  AVCodec* video_codec = avcodec_find_encoder(AV_CODEC_ID_H264);
  avcodec_open2(video_codec, NULL, NULL);

  AVStream* audio_stream = NULL;
  AVCodec* audio_codec = NULL;

  AVFrame* video_frame = av_frame_alloc();
  AVPacket video_pkt;

  while (av_read_frame(input_context, &video_pkt) >= 0) {
    if (video_pkt.stream_index == video_stream->index) {
      avcodec_encode_video2(video_codec, &video_pkt, video_frame, &got_packet);
      if (got_packet) {
        av_interleaved_write_frame(output_context, &video_pkt);
        av_packet_unref(&video_pkt);
      }
    }
  }

  avcodec_close(video_codec);

  if (audio_stream) {
    avcodec_close(audio_codec);
  }

  avformat_close_input(&input_context);
  avformat_free_context(output_context);

  return 0;
}

常见问题解答

1. 我可以使用 H.264 编码其他类型的文件吗?

是的,H.264 是一种通用编解码器,可用于编码各种视频格式,包括 MOV、AVI 和 MKV。

2. MP4 和 H.264 之间的区别是什么?

MP4 是一个容器格式,可以包含视频、音频和字幕等多种数据流。H.264 是一种视频编解码器,用于压缩和解压缩视频数据。

3. 我需要使用什么软件来编码图像?

可以使用多种软件来编码图像,包括 FFmpeg、HandBrake 和 VLC Media Player。

4. 如何优化我的编码设置?

编码设置会影响输出视频的质量和文件大小。您需要根据您的特定需求调整这些设置,例如比特率、帧率和分辨率。

5. 我的编码视频为什么会失真或有噪音?

编码视频失真或噪音可能是由多种因素造成的,包括比特率不足、编码器设置不当或源文件质量差。