

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!
由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新
pkt->size = 0;
decode(c, pkt, decoded_frame, outfile);
fclose(outfile);
fclose(f);
avcodec_free_context(&c);
av_parser_close(parser);
av_frame_free(&decoded_frame);
av_packet_free(&pkt);
return 0;
}
### 2、音频编码 Encode\_audio
将原始数pcm文件编码成mp3,可直接双击播放的

#include
#include
using namespace std;
/*
文件解封装测试
*/
#ifdef __cplusplus
extern “C”
{
#endif // !__cplusplus
#include “libavutil/opt.h”
#include <libavutil/imgutils.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include “libswresample/swresample.h”//包含头文件
#include <libavutil/imgutils.h>
#include <libavutil/time.h>
#ifdef __cplusplus
}
#endif // !__cplusplus
#pragma comment(lib,“avformat.lib”)//添加库文件,也可以在属性处添加
#pragma comment(lib,“avutil.lib”)
#pragma comment(lib,“avcodec.lib”)
#pragma comment(lib,“swresample.lib”)
#pragma comment(lib,“swscale.lib”)
int main()
{
AVFormatContext* pFormatCtx;
AVOutputFormat* fmt;
AVStream* audio_st;
AVCodecContext* pCodecCtx;
AVCodec* pCodec;
uint8_t* frame_buf;
AVFrame* pFrame;
AVPacket pkt;
int got_frame = 0;
int ret = 0;
int size = 0;
FILE *in_file = NULL; //Raw PCM data
int framenum = 10000; //Audio frame number
const char* out_file = "test.mp3"; //Output URL
int i;
in_file = fopen("D:/yuv_file11.pcm", "rb");
av_register_all();
//Method 1.
pFormatCtx = avformat_alloc_context();
fmt = av_guess_format(NULL, out_file, NULL);
pFormatCtx->oformat = fmt;
//Method 2.
//avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);
//fmt = pFormatCtx->oformat;
//Open output URL
if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0) {
printf("Failed to open output file!\n");
return -1;
}
audio_st = avformat_new_stream(pFormatCtx, 0);
if (audio_st == NULL) {
return -1;
}
pCodecCtx = audio_st->codec;
pCodecCtx->codec_id = fmt->audio_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_AUDIO;
pCodecCtx->sample_fmt = AV_SAMPLE_FMT_S16;// AV_SAMPLE_FMT_FLTP;// AV_SAMPLE_FMT_S16;
pCodecCtx->sample_rate = 44100;// 44100; 16000
pCodecCtx->channel_layout = av_get_default_channel_layout(1);
pCodecCtx->channels = av_get_channel_layout_nb_channels(pCodecCtx->channel_layout);
pCodecCtx->bit_rate = 64000; //64000; 15000
pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec) {
printf("Can not find encoder!\n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, NULL) < 0) {
printf("Failed to open encoder!\n");
return -1;
}
pFrame = av_frame_alloc();
pFrame->nb_samples = pCodecCtx->frame_size;
pFrame->format = pCodecCtx->sample_fmt;
size = av_samples_get_buffer_size(NULL, pCodecCtx->channels, pCodecCtx->frame_size, pCodecCtx->sample_fmt, 1);
frame_buf = (uint8_t *)av_malloc(size);
avcodec_fill_audio_frame(pFrame, pCodecCtx->channels, pCodecCtx->sample_fmt, (const uint8_t*)frame_buf, size, 1);
//Write Header
avformat_write_header(pFormatCtx, NULL);
av_new_packet(&pkt, size);
for (i = 0; ; i++) {
//Read PCM
if (fread(frame_buf, 1, size, in_file) <= 0) {
printf("Failed to read raw data! \n");
return -1;
}
else if (feof(in_file)) {
break;
}
pFrame->data[0] = frame_buf; //PCM Data
pFrame->pts = i * 100;
got_frame = 0;
//Encode
ret = avcodec_encode_audio2(pCodecCtx, &pkt, pFrame, &got_frame);
if (ret < 0) {
printf("Failed to encode!\n");
return -1;
}
if (got_frame == 1) {
printf("Succeed to encode 1 frame! \tsize:%5d\n", pkt.size);
pkt.stream_index = audio_st->index;
ret = av_write_frame(pFormatCtx, &pkt);
av_free_packet(&pkt);
}
}
Flush Encoder
//ret = flush_encoder(pFormatCtx, 0);
//if (ret < 0) {
// printf("Flushing encoder failed\n");
// return -1;
//}
//Write Trailer
av_write_trailer(pFormatCtx);
//Clean
if (audio_st) {
avcodec_close(audio_st->codec);
av_free(pFrame);
av_free(frame_buf);
}
avio_close(pFormatCtx->pb);
avformat_free_context(pFormatCtx);
fclose(in_file);
getchar();
return 0;
}
### 3、视频解码 Decode\_video
将h264文件解码生成yuv文件
#include
#include
using namespace std;
/*
文件解封装测试
*/
#ifdef __cplusplus
extern “C”
{
#endif // !__cplusplus
#include “libavutil/opt.h”
#include <libavutil/imgutils.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include “libswresample/swresample.h”//包含头文件
#include <libavutil/imgutils.h>
#include <libavutil/time.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#ifdef __cplusplus
}
#endif // !__cplusplus
#pragma comment(lib,“avformat.lib”)//添加库文件,也可以在属性处添加
#pragma comment(lib,“avutil.lib”)
#pragma comment(lib,“avcodec.lib”)
#pragma comment(lib,“swresample.lib”)
#pragma comment(lib,“swscale.lib”)
#define INBUF_SIZE 4096
/*
将h264文件解码成一张张YUV图片
*/
static void pgm_save(unsigned char *buf, int wrap, int xsize, int ysize,
char *filename)
{
FILE *f;
int i;
f = fopen(filename, "w");
fprintf(f, "P5\n%d %d\n%d\n", xsize, ysize, 255);
for (i = 0; i < ysize; i++)
fwrite(buf + i * wrap, 1, xsize, f);
fclose(f);
}
static void decode(AVCodecContext *dec_ctx, AVFrame *frame, AVPacket *pkt,
const char *filename)
{
char buf[1024];
int ret;
ret = avcodec_send_packet(dec_ctx, pkt);
if (ret < 0) {
fprintf(stderr, "Error sending a packet for decoding\n");
exit(1);
}
while (ret >= 0) {
ret = avcodec_receive_frame(dec_ctx, frame);
if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
return;
else if (ret < 0) {
fprintf(stderr, "Error during decoding\n");
exit(1);
}
printf("saving frame %3d\n", dec_ctx->frame_number);
fflush(stdout);
/* the picture is allocated by the decoder. no need to
free it */
snprintf(buf, sizeof(buf), "%s-%d", filename, dec_ctx->frame_number);
pgm_save(frame->data[0], frame->linesize[0],
frame->width, frame->height, buf);
}
}
int main(int argc, char **argv)
{
const char *filename, *outfilename;
const AVCodec *codec;
AVCodecParserContext *parser;
AVCodecContext *c = NULL;
FILE *f;
AVFrame *frame;
uint8_t inbuf[INBUF_SIZE + AV_INPUT_BUFFER_PADDING_SIZE];
uint8_t *data;
size_t data_size;
int ret;
AVPacket *pkt;
filename = "ds.h264";
outfilename = "ds.yuv";
pkt = av_packet_alloc();
if (!pkt)
exit(1);
/* set end of buffer to 0 (this ensures that no overreading happens for damaged MPEG streams) */
memset(inbuf + INBUF_SIZE, 0, AV_INPUT_BUFFER_PADDING_SIZE);
/* find the MPEG-1 video decoder */
codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
fprintf(stderr, "Codec not found\n");
exit(1);
}
parser = av_parser_init(codec->id);
if (!parser) {
fprintf(stderr, "parser not found\n");
exit(1);
}
c = avcodec_alloc_context3(codec);
if (!c) {
fprintf(stderr, "Could not allocate video codec context\n");
exit(1);
}
/* For some codecs, such as msmpeg4 and mpeg4, width and height
MUST be initialized there because this information is not
available in the bitstream. */
/* open it */
if (avcodec_open2(c, codec, NULL) < 0) {
fprintf(stderr, "Could not open codec\n");
exit(1);
}
f = fopen(filename, "rb");
if (!f) {
fprintf(stderr, "Could not open %s\n", filename);
exit(1);
}
frame = av_frame_alloc();
if (!frame) {
fprintf(stderr, "Could not allocate video frame\n");
exit(1);
}
while (!feof(f)) {
/* read raw data from the input file */
data_size = fread(inbuf, 1, INBUF_SIZE, f);
if (!data_size)
break;
/* use the parser to split the data into frames */
data = inbuf;
while (data_size > 0) {
ret = av_parser_parse2(parser, c, &pkt->data, &pkt->size,
data, data_size, AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0);
if (ret < 0) {
fprintf(stderr, "Error while parsing\n");
exit(1);
}
data += ret;
data_size -= ret;
if (pkt->size)
decode(c, frame, pkt, outfilename);
}
}
/* flush the decoder */
decode(c, frame, NULL, outfilename);
fclose(f);
av_parser_close(parser);
avcodec_free_context(&c);
av_frame_free(&frame);
av_packet_free(&pkt);
return 0;
}
### 4、视频编码 Encode\_video
将YUV编码生成H264文件

#include
#include
using namespace std;
/*
文件解封装测试
*/
#ifdef __cplusplus
extern “C”
{
#endif // !__cplusplus
#include “libavutil/opt.h”
#include <libavutil/imgutils.h>
#include <libavformat/avformat.h>
#include <libavformat/avio.h>
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
#include “libswresample/swresample.h”//包含头文件
#include <libavutil/imgutils.h>
#include <libavutil/time.h>
#include <libavutil/channel_layout.h>
#include <libavutil/common.h>
#include <libavutil/frame.h>
#include <libavutil/samplefmt.h>
#ifdef __cplusplus
}
#endif // !__cplusplus
#pragma comment(lib,“avformat.lib”)//添加库文件,也可以在属性处添加
#pragma comment(lib,“avutil.lib”)
#pragma comment(lib,“avcodec.lib”)
#pragma comment(lib,“swresample.lib”)
#pragma comment(lib,“swscale.lib”)
/*
将YUV数据编码成h264文件
/
int main(int argc, char argv[])
{
AVFormatContext* pFormatCtx;
AVOutputFormat* fmt;
AVStream* video_st;
AVCodecContext* pCodecCtx;
AVCodec* pCodec;
AVPacket* pkt;
uint8_t* picture_buf;
uint8_tpFrame_buf;
AVFrame pFrame;
int picture_size;
int y_size;
int framecnt = 0;
int ret;
//FILE *in_file = fopen(“src01_480x272.yuv”, “rb”); //Input raw YUV data
FILE *in_file = fopen(“output240X128.yuv”, “rb”); //Input raw YUV data
if (in_file == NULL)
{
printf(“Failed fopen file! \n”);
return -1;
}
int in_w = 240, in_h = 128; //Input data's width and height
int framenum = 100;
const char* out_file = "ds.h264";
av_register_all();
/*
//Method1.
pFormatCtx = avformat_alloc_context();
//av_guess_format在注册输出格式列表中返回与所提供的参数最匹配的输出格式,如果没有匹配则返回NULL。
fmt = av_guess_format(NULL, out_file, NULL);//根据文件名去匹配输出格式AVOutputFormat
pFormatCtx->oformat = fmt;
*/
//Method 2.
//为输出格式分配一个AVFormatContext。
//int avformat_alloc_output_context2(AVFormatContext **ctx, AVOutputFormat *oformat,const char *format_name, const char *filename);
//oformat用于分配上下文的格式,如果为NULL则用format_name、filename代替
//format_name用于分配上下文的输出格式的名称,如果为NULL则使用filename文件名代替
//filename用于分配上下文的文件名
avformat_alloc_output_context2(&pFormatCtx, NULL, NULL, out_file);
fmt = pFormatCtx->oformat;
//Open output URL
//创建并初始化一个AVIOContext,用于访问url指示的资源。
if (avio_open(&pFormatCtx->pb, out_file, AVIO_FLAG_READ_WRITE) < 0) {
printf("Failed to open output file! \n");
return -1;
}
video_st = avformat_new_stream(pFormatCtx, 0);
//video_st->time_base.num = 1;
//video_st->time_base.den = 25;
if (video_st == NULL) {
return -1;
}
//Param that must set
pCodecCtx = video_st->codec;
//pCodecCtx->codec_id =AV_CODEC_ID_HEVC;
pCodecCtx->codec_id = fmt->video_codec;
pCodecCtx->codec_type = AVMEDIA_TYPE_VIDEO;
pCodecCtx->pix_fmt = AV_PIX_FMT_YUV420P;
pCodecCtx->width = in_w;
pCodecCtx->height = in_h;
pCodecCtx->bit_rate = 400000;
pCodecCtx->gop_size = 250;
pCodecCtx->time_base.num = 1;
pCodecCtx->time_base.den = 25;
//H264
//pCodecCtx->me_range = 16;
//pCodecCtx->max_qdiff = 4;
//pCodecCtx->qcompress = 0.6;
pCodecCtx->qmin = 10;
pCodecCtx->qmax = 51;
//Optional Param
pCodecCtx->max_b_frames = 3;
// Set Option
AVDictionary *param = 0;
//H.264
if (pCodecCtx->codec_id == AV_CODEC_ID_H264) {
av_dict_set(¶m, "preset", "slow", 0);
av_dict_set(¶m, "tune", "zerolatency", 0);
//av_dict_set(param, "profile", "main", 0);
}
//H.265
if (pCodecCtx->codec_id == AV_CODEC_ID_H265) {
av_dict_set(¶m, "preset", "ultrafast", 0);
av_dict_set(¶m, "tune", "zero-latency", 0);
}
//Show some Information
av_dump_format(pFormatCtx, 0, out_file, 1);
//查找具有匹配编解码器ID的已注册编码器。
pCodec = avcodec_find_encoder(pCodecCtx->codec_id);
if (!pCodec) {
printf("Can not find encoder! \n");
return -1;
}
if (avcodec_open2(pCodecCtx, pCodec, ¶m) < 0) {
printf("Failed to open encoder! \n");
return -1;
}
//存储一帧像素数据缓冲区
pFrame = av_frame_alloc();
picture_size = av_image_get_buffer_size(pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height, 1);
picture_buf = (uint8_t *)av_malloc(picture_size);
pFrame_buf = (uint8_t *)av_malloc(picture_size);
//av_image_fill_arrays((AVPicture *)pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);//淘汰了


网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
1);
picture_buf = (uint8_t *)av_malloc(picture_size);
pFrame_buf = (uint8_t *)av_malloc(picture_size);
//av_image_fill_arrays((AVPicture *)pFrame, picture_buf, pCodecCtx->pix_fmt, pCodecCtx->width, pCodecCtx->height);//淘汰了
[外链图片转存中…(img-rvSwHBa1-1715745455524)]
[外链图片转存中…(img-vmsS0T7g-1715745455524)]
网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。
一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
2万+

被折叠的 条评论
为什么被折叠?



