视频编码h264怎么看_你所要知道的音视频--04

8d88afda916f9bee1cc65dad9a1ad810.png

上一篇文章我们主要讲解了音频压缩算法的主要指标,以及几个典型的音频压缩算法。本章将延续上一讲的内容,分析视频压缩算法。

视频压缩算法

视频压缩算法比较,Wiki百科官方收录分类,请自备梯子

视频压缩算法比较​en.wikipedia.org

这里建议大家关注三个东西。H264/5,DCT算法,FFmpeg开源库。

目前市面上主流的视频编码算法有:x264/5,vp8/9。本文简单记录一下它们的编译方法。其中x264现在占据着H.264视频编码器的半壁江山,x265则是目前实现H.265标准最好的开源视频编码器。是x264的潜在替代者。而vp8/9则是Google推出的开源视频编码器,它提出的VP9编码标准的性能也不错,但目前主要是Google这家公司在玩。

对于视频的编解码,常常还会涉及到专用硬件加速。这一块本文不涉及。

视频压缩性能衡量指标

  1. 有损/无损编码:
  2. 压缩比:实际输入数据量与输出数据量的比值
  3. 编解码时间(时延):编解码复杂度:
  4. 可变帧率(VFR)
  5. 兼容的封装格式

其他几个东西都比较好理解,那这个封装格式是一个什么东西呢?其实就是打包视频、音频、字幕等的方式。具体的我们会在下一章中讲到。

在视频中,由于数据量较大,所以相对于音频编解码算法,视频的编解码算法对于编解码时间还是比较关注的。真是因为这种编解码算法都是运算量极大的算法,因此一般核心音视频软件都是通过C/C++撰写的,同时还要关注其对于CPU资源的需求量,必要时通过GPU调优。

H264 编码

H.264是MPEG4的第十部分,是一个高级视频编码(AVC)标准。是一种面向块,基于运动补偿的编码算法。与旧标准(H.263)相比,它能够在更低带宽下提供优质视频,且复杂度适中,实现难度适中。因此,得到了广泛的发展。

H.264标准可以被看作一个“标准家族”,成员有下面描述的各种配置(profile)。一个特定的解码器至少支持一种,但不必支持所有的。解码器标准描述了它可以解码哪些配置。

更多细节可以参考Wiki百科:H.264标准

提到H264标准,就不得不提x264算法实现了。x264其实就是目前最流行的H264标准的算法实现库。而大名鼎鼎的FFmpeg对于H264的编码就是用的x264代码库。其中有一个特别显眼的注释: H.264 encoding using the x264 library

x264是H264标准的算法实现库:

x264 官方​www.videolan.org

所以H264、x264以及FFmpeg三者的关系可以概括为:H.264是标准(包含编码、解码),x264是标准的实现(只实现了编码),FFmpeg是一个框架,但是里面包含了H.264的解码实现,编码采用了x264。

H264 算法细节

英语标准原稿​read.pudn.com

首先,我们先看看编解码的整体结构,有个全局观。

848bf9949a51fa22fd2700c26dd04f43.png

好了,接下来放大招了:

ITU H264标准文档​www.itu.int

简直是一份全英文的数学公式,你别妄想着个把月能搞懂里面所有的东西(别问我怎么知道的),用的时候来查就好了,建议直接看Annex。接下来我们就进入正题了。

Profile和Level

H264定义了很多中的Profile来限定具体实现的H264算法的能力,然后通过

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您好,针对您的问题,我可以给出如下思路: 1. 使用FFmpeg的C++ API来编码H264和AAC数据流,并将它们混合在一起。 2. 对于每个视频帧和音频帧,使用PTS(Presentation Time Stamp)来保证它们的时间戳是正确的。 3. 将编码后的H264和AAC数据流写入一个文件中,同时确保它们的时间戳是同步的。 下面是一个简单的示例代码,仅供参考: ``` #include <iostream> #include <string> #include <vector> #include <chrono> #include <thread> extern "C" { #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libavutil/opt.h> #include <libavutil/timestamp.h> #include <libavutil/audio_fifo.h> } #define AUDIO_SAMPLE_RATE 48000 #define AUDIO_CHANNELS 2 #define AUDIO_FORMAT AV_SAMPLE_FMT_FLT #define AUDIO_BITRATE 128000 using namespace std; int main(int argc, char* argv[]) { // Initialize FFmpeg av_register_all(); avcodec_register_all(); // Open video output file AVFormatContext* out_ctx; avformat_alloc_output_context2(&out_ctx, NULL, NULL, "output.mp4"); AVStream* video_stream = avformat_new_stream(out_ctx, NULL); AVStream* audio_stream = avformat_new_stream(out_ctx, NULL); // Configure video stream AVCodec* video_codec = avcodec_find_encoder(AV_CODEC_ID_H264); AVCodecContext* video_ctx = avcodec_alloc_context3(video_codec); video_ctx->bit_rate = 400000; video_ctx->width = 640; video_ctx->height = 480; video_ctx->time_base = { 1, 25 }; video_ctx->gop_size = 10; video_ctx->max_b_frames = 1; avcodec_open2(video_ctx, video_codec, NULL); avcodec_parameters_from_context(video_stream->codecpar, video_ctx); video_stream->time_base = video_ctx->time_base; // Configure audio stream AVCodec* audio_codec = avcodec_find_encoder(AV_CODEC_ID_AAC); AVCodecContext* audio_ctx = avcodec_alloc_context3(audio_codec); audio_ctx->sample_rate = AUDIO_SAMPLE_RATE; audio_ctx->channels = AUDIO_CHANNELS; audio_ctx->sample_fmt = AUDIO_FORMAT; audio_ctx->bit_rate = AUDIO_BITRATE; audio_ctx->time_base = { 1, AUDIO_SAMPLE_RATE }; avcodec_open2(audio_ctx, audio_codec, NULL); avcodec_parameters_from_context(audio_stream->codecpar, audio_ctx); audio_stream->time_base = audio_ctx->time_base; // Open output file avio_open(&out_ctx->pb, "output.mp4", AVIO_FLAG_WRITE); // Write header to output file avformat_write_header(out_ctx, NULL); // Encode and write frames to output file for (int i = 0; i < 100; i++) { // Encode video frame AVFrame* video_frame = av_frame_alloc(); video_frame->width = video_ctx->width; video_frame->height = video_ctx->height; video_frame->format = video_ctx->pix_fmt; av_frame_get_buffer(video_frame, 0); // Fill video frame with data... avcodec_send_frame(video_ctx, video_frame); AVPacket video_pkt; av_init_packet(&video_pkt); avcodec_receive_packet(video_ctx, &video_pkt); video_pkt.stream_index = video_stream->index; video_pkt.pts = i * video_ctx->time_base.den / (video_ctx->time_base.num * 25); video_pkt.dts = video_pkt.pts; av_interleaved_write_frame(out_ctx, &video_pkt); av_packet_unref(&video_pkt); av_frame_free(&video_frame); // Encode audio frame AVFrame* audio_frame = av_frame_alloc(); audio_frame->sample_rate = audio_ctx->sample_rate; audio_frame->channels = audio_ctx->channels; audio_frame->format = audio_ctx->sample_fmt; av_frame_get_buffer(audio_frame, 0); // Fill audio frame with data... avcodec_send_frame(audio_ctx, audio_frame); AVPacket audio_pkt; av_init_packet(&audio_pkt); avcodec_receive_packet(audio_ctx, &audio_pkt); audio_pkt.stream_index = audio_stream->index; audio_pkt.pts = i * audio_ctx->time_base.den / AUDIO_SAMPLE_RATE; audio_pkt.dts = audio_pkt.pts; av_interleaved_write_frame(out_ctx, &audio_pkt); av_packet_unref(&audio_pkt); av_frame_free(&audio_frame); // Sleep for a while to simulate real-time processing this_thread::sleep_for(chrono::milliseconds(40)); } // Write trailer to output file av_write_trailer(out_ctx); // Close output file avio_close(out_ctx->pb); avformat_free_context(out_ctx); // Cleanup FFmpeg avcodec_free_context(&video_ctx); avcodec_free_context(&audio_ctx); return 0; } ``` 在上述示例代码中,我们先初始化了FFmpeg,并创建了一个输出文件。然后,我们分别配置了视频流和音频流的编码参数,并将它们添加到输出文件中。接下来,我们编码并写入了100个视频帧和音频帧,并使用PTS保证它们的时间戳是正确的。最后,我们写入了输出文件的尾部,并关闭了输出文件。 请注意,上述示例代码仅供参考,您需要根据自己的实际需求进行修改和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值