外贸建站费用,劳动法24小时免费咨询,建设英文网站要求,广告信息发布平台视频解码
初始化
视频常用的编解码器id定义#xff08;以h264和h265为例#xff09;
// 定义在ffmpeg\include\libavcodec\avcodec.h
AV_CODEC_ID_H264
AV_CODEC_ID_H265查找解码器#xff1a;根据编解码id查看解码器
AVCodec* pCodecVideo avcodec_find_decoder(codec…视频解码
初始化
视频常用的编解码器id定义以h264和h265为例
// 定义在ffmpeg\include\libavcodec\avcodec.h
AV_CODEC_ID_H264
AV_CODEC_ID_H265查找解码器根据编解码id查看解码器
AVCodec* pCodecVideo avcodec_find_decoder(codecID);
if (!pCodecVideo)
{printf(avcodec_find_decoder failed\n);return -1;
}申请编码器上下文结构体内存保存了视频编解码相关信息
AVCodecContext* pCodecCtxVideo avcodec_alloc_context3(pCodecVideo);
if (!pCodecCtxVideo)
{printf(avcodec_alloc_context3 error\n);return -1;
}打开解码器
if (avcodec_open2(pCodecCtxVideo, pCodecVideo, NULL) 0)
{printf(avcodec_open2 failed\n);return -1;
}申请帧内存存储一帧解码后像素采样数据
AVFrame* pFrameVideo av_frame_alloc();
if (!pFrameVideo)
{printf(av_frame_alloc failed\n);return -1;
}视频解码
解码一帧压缩数据
// data和len为压缩数据的指针和大小AVPacket packet;
av_init_packet(packet);
packet.data (uint8_t*)data;
packet.size len;int got_picture 0;
if (avcodec_decode_video2(pCodecCtxVideo, pFrameVideo, got_picture, packet) 0)
{printf(avcodec_decode_video2 failed\n);return -1;
}获取帧大小
// 以YUV420为例
int frameSize avpicture_get_size(AV_PIX_FMT_YUV420P, pFrameVideo-linesize[0], pFrameVideo-height);获取上下文获取用于转码的参数**初始化一次**
// pFrameVideo-width输入帧数据宽
// pFrameVideo-height输入帧数据高
// pCodecCtxVideo-pix_fmt帧数据格式
// pFrameVideo-width输出帧数据宽
// pFrameVideo-height输出帧数据高
// AV_PIX_FMT_YUV420P输出帧数据格式,例如YUV420、RGB32等
// SWS_BICUBIC视频像素数据格式转换算法类型
SwsContext* imgConvertCtx sws_getContext(pFrameVideo-width, pFrameVideo-height,pCodecCtxVideo-pix_fmt,pFrameVideo-width, pFrameVideo-height, AV_PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);缓冲区分配缓存**初始化一次**
int frameSize avpicture_get_size(AV_PIX_FMT_YUV420P, pFrameVideo-width, pFrameVideo-height);
AVFrame* picture av_frame_alloc();
uint8_t* pictureBuf new uint8_t[frameSize];初始化缓冲区**初始化一次**
avpicture_fill((AVPicture *)m_picture, m_pictureBuf, AV_PIX_FMT_YUV420P, pFrameVideo-width, pFrameVideo-height);图片转换**针对实时流或读取的文件流循环调用**
sws_scale(imgConvertCtx, (const uint8_t* const*)pFrameVideo-data, pFrameVideo-linesize, 0, pFrameVideo-height, picture-data, picture-linesize);解码关闭
if (nullptr ! pCodecCtxVideo)
{avcodec_close(pCodecCtxVideo);av_free(pCodecCtxVideo);pCodecCtxVideo nullptr;
}if (nullptr ! pFrameVideo)
{av_frame_free(pFrameVideo);pFrameVideo nullptr;
}if (nullptr ! picture)
{av_frame_free(picture);picture nullptr;
}if (nullptr ! pictureBuf)
{delete[] pictureBuf;pictureBuf nullptr;
}if (nullptr ! imgConvertCtx)
{sws_freeContext(imgConvertCtx);imgConvertCtx nullptr;
}音频解码
初始化
音频常用的编解码器id定义
AV_CODEC_ID_PCM_ALAW
AV_CODEC_ID_PCM_MULAW
AV_CODEC_ID_FIRST_AUDIO
AV_CODEC_ID_AAC查找解码器根据编解码id查看解码器
AVCodec* pCodecAudio avcodec_find_decoder(codecID);
if (!pCodecAudio)
{printf(audio avcodec_find_decoder failed\n);return -1;
}申请编码器上下文结构体内存保存了音频编解码相关信息
AVCodecContext* pCodecCtxAudio avcodec_alloc_context3(pCodecAudio);
if (!pCodecCtxAudio)
{printf(audio avcodec_alloc_context3 failed\n);return -1;
}打开解码器
int audioCodecType (int)codec;
switch (audioCodecType)
{case CODEC_AUDIO_AAC:break;case CODEC_AUDIO_MP3:break;case CODEC_AUDIO_G711:case CODEC_AUDIO_G711U:pCodecCtxAudio-codec_type AVMEDIA_TYPE_AUDIO;pCodecCtxAudio-sample_fmt AV_SAMPLE_FMT_S16;pCodecCtxAudio-sample_rate 8000;pCodecCtxAudio-channel_layout AV_CH_LAYOUT_MONO;pCodecCtxAudio-channels 1;break;case CODEC_AUDIO_G7231:break;case CODEC_AUDIO_G7221:break;default:break;
}pCodecCtxAudio-codec_id codecID;
int ret avcodec_open2(pCodecCtxAudio, pCodecAudio, NULL);
if (ret 0)
{printf(audio avcodec_open2 failed\n);return -1;
}申请内存和初始化参数
AVFrame* frameAudio av_frame_alloc();
if (!frameAudio)
{printf(audio av_frame_alloc failed\n);return -1;
}AVPacket* audioPacket av_packet_alloc();
if (!audioPacket)
{printf(av_packet_alloc failed\n);return -1;
}
av_init_packet(audioPacket);音频解码
解码一帧音频数据
audioPacket-data (uint8_t*)data;
audioPacket-size datalen;int ret avcodec_send_packet(m_pCodecCtxAudio, m_audioPacket);
if (ret 0)
{av_packet_unref(audioPacket);printf(audio avcodec_send_packet failed\n);return -1;
}接收一帧数据
ret avcodec_receive_frame(m_pCodecCtxAudio, m_frameAudio);
if (ret 0)
{return -1;
}设置输入和输出音频信息**执行一次**
// 分配SwrContext
SwrContext* audioSwrCtx swr_alloc();
int channelLayout av_get_default_channel_layout(frameAudio-channels);// audioSwrCtx重采样申请的内存。如果传NULL内部会申请一块内存非NULL可以复用之前的内存
// AV_CH_LAYOUT_MONO目标声道
// AV_SAMPLE_FMT_S16目标采样格式
// frameAudio-sample_rate目标采样率
// channelLayout原始声道布局
// pCodecCtxAudio-sample_fmt原始采样格式
// frameAudio-sample_rate原始采样率
// 设置输入和输出的音频信息
swr_alloc_set_opts(audioSwrCtx, AV_CH_LAYOUT_MONO, AV_SAMPLE_FMT_S16,frameAudio-sample_rate,channelLayout, pCodecCtxAudio-sample_fmt, frameAudio-sample_rate, 0, NULL);// 设置用户参数后初始化上下文
swr_init(audioSwrCtx);重采样转换循环执行
// audioSwrCtx音频重采样的上下文
// audioBuffer输出的指针。传递的输出的数组
// 1024*256输出的样本数量不是字节数。单通道的样本数量。
// (const uint8_t**)frameAudio-data输入的数组AVFrame解码出来的DATA
// frameAudio-nb_samples输入的单通道的样本数量。
// 以单声道为例
int len swr_convert(audioSwrCtx, audioBuffer, 1024*256,(const uint8_t**)frameAudio-data,frameAudio-nb_samples);// 获取音频大小
av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO);
int bufSize av_samples_get_buffer_size(NULL, av_get_channel_layout_nb_channels(AV_CH_LAYOUT_MONO),frameAudio-nb_samples,AV_SAMPLE_FMT_S16, 0);解码关闭
if (nullptr ! pCodecCtxAudio)
{avcodec_close(pCodecCtxAudio);av_free(pCodecCtxAudio);pCodecCtxAudio nullptr;
}if (nullptr ! frameAudio)
{av_frame_free(frameAudio);frameAudio nullptr;
}if (nullptr ! audioPacket)
{av_packet_unref(audioPacket);av_packet_free(audioPacket);audioPacket nullptr;
}if (nullptr ! audioSwrCtx)
{swr_free(audioSwrCtx);audioSwrCtx nullptr;
}// 其他资源释放