AntiClipSettings/H264Palyer.cpp
2024-08-13 20:06:10 +08:00

66 lines
2.0 KiB
C++

#include "H264Palyer.h"
#include "BoostLog.h"
extern "C" {
#include <libavcodec/avcodec.h>
#include <libswscale/swscale.h>
}
H264Palyer::H264Palyer() {
}
H264Palyer::~H264Palyer() {
if (m_packet != nullptr) {
av_packet_free(&m_packet);
}
}
void H264Palyer::open() {
auto codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!codec) {
LOG(error) << "cannot find h264 codec.";
return;
}
m_codecContext = avcodec_alloc_context3(codec);
if (m_codecContext == nullptr) {
LOG(error) << "Could not allocate video codec context";
return;
}
if (avcodec_open2(m_codecContext, codec, nullptr) < 0) {
LOG(error) << "Could not open codec";
return;
}
m_packet = av_packet_alloc();
if (m_packet == nullptr) {
LOG(error) << "Could not allocate AVPacket";
}
m_frame = av_frame_alloc();
if (m_frame == nullptr) {
LOG(error) << "Could not allocate AVFrame";
}
}
std::optional<QImage> H264Palyer::decode(const uint8_t *data, uint32_t size) {
m_packet->data = const_cast<uint8_t *>(data);
m_packet->size = size;
int ret = avcodec_send_packet(m_codecContext, m_packet);
if (ret < 0) {
return std::nullopt;
}
ret = avcodec_receive_frame(m_codecContext, m_frame);
if (ret < 0) {
return std::nullopt;
}
SwsContext *swsCtx = sws_getContext(m_frame->width, m_frame->height, m_codecContext->pix_fmt, m_frame->width,
m_frame->height, AV_PIX_FMT_RGB24, SWS_BILINEAR, nullptr, nullptr, nullptr);
QImage image(m_frame->width, m_frame->height, QImage::Format_RGB888);
uint8_t *imageData[1] = {image.bits()};
int linesize[1] = {3 * m_frame->width};
sws_scale(swsCtx, m_frame->data, m_frame->linesize, 0, m_frame->height, imageData, linesize);
sws_freeContext(swsCtx);
// LOG(info) << image.width() << "x" << image.height();
return image;
}