继桌面采集之后的第二篇关于音视频的文章,本篇主要实现视频的转码,将采集的BRGA转码为YUV420。
技术简介
使用ffmpeg sws实现转码。
使用模块(库)
ffmpeg的swscale-5.dll
主要流程和代码
1、初始化转码器,srcFmt是AV_PIX_FMT_BGRA,dstFmt是AV_PIX_FMT_YUV420P
int FfmpegSwsTranscoder::init(AVPixelFormat srcFmt, int srcWidth, int srcHeight, AVPixelFormat dstFmt, int dstWidth, int dstHeight)
{
int err = ERROR_CODE_OK;
if (m_inited) {
return err;
}
m_swsContext = sws_getContext(srcWidth, srcHeight, srcFmt, dstWidth, dstHeight, dstFmt,
SWS_BICUBIC, nullptr, nullptr, nullptr);
if (m_swsContext == nullptr) {
err = ERROR_CODE_FFMPEG_GET_SWS_CONTEXT_FAILED;
return err;
}
m_bufferSize = av_image_get_buffer_size(dstFmt, dstWidth, dstHeight, 1);
m_buffer = (uint8_t*)av_malloc(m_bufferSize);
if (m_buffer == nullptr) {
err = ERROR_CODE_ALLOC_FAILED;
return err;
}
m_frame = av_frame_alloc();
if (m_frame == nullptr) {
err = ERROR_CODE_FFMPEG_ALLOC_FRAME_FAILED;
return err;
}
int ret = av_image_fill_arrays(m_frame->data, m_frame->linesize, m_buffer, dstFmt, dstWidth, dstHeight, 1);
if (ret < 0) {
err = ERROR_CODE_FFMPEG_FILL_IMAGE_FAILED;
return err;
}
m_inited = true;
return err;
}
2、转码
int FfmpegSwsTranscoder::transcode(const AVFrame* srcFrame, AVFrame** dstFrame, uint8_t** dstData, uint32_t* dstLen)
{
int err = ERROR_CODE_OK;
if (!m_inited || m_swsContext == nullptr) {
err = ERROR_CODE_UNINITIALIZED;
return err;
}
int ret = sws_scale(m_swsContext, srcFrame->data, srcFrame->linesize, 0, srcFrame->height,
m_frame->data, m_frame->linesize);
if (ret <= 0) {
err = ERROR_CODE_FFMPEG_SWS_SCALE_FAILED;
return err;
}
m_frame->format = srcFrame->format;
m_frame->width = srcFrame->width;
m_frame->height = srcFrame->height;
m_frame->pict_type = srcFrame->pict_type;
m_frame->pts = srcFrame->pts;
m_frame->pkt_dts = srcFrame->pkt_dts;
*dstFrame = m_frame;
*dstData = m_buffer;
*dstLen = m_bufferSize;
return err;
}
至此,就可以拿到视频帧数据进行下一步操作了,那就是编码。
PS:视频转码是音视频技术中使用起来相对简单的一个了。