66 lines
2.0 KiB
C++
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;
|
|
}
|