FFmpegPlayer/VideoDecoder.cpp

61 lines
2.0 KiB
C++
Raw Permalink Normal View History

2024-01-18 22:22:26 +08:00
#include "VideoDecoder.h"
#include "BoostLog.h"
extern "C" {
#include "libavcodec/avcodec.h"
}
VideoDecoder::VideoDecoder(const AVCodec *codec, const AVCodecParameters *parameters) {
m_context = avcodec_alloc_context3(codec);
avcodec_parameters_to_context(m_context, parameters);
avcodec_open2(m_context, codec, nullptr);
}
void VideoDecoder::start() {
m_exit = false;
m_thread = std::thread(&VideoDecoder::run, this);
}
void VideoDecoder::push(const std::shared_ptr<AVPacket> &packet) {
std::lock_guard locker(m_mutex);
LOG(info) << "dts: " << packet->dts << ", pts: " << packet->pts;
m_packets.push(packet);
}
void VideoDecoder::run() {
using namespace std::chrono_literals;
auto frame = av_frame_alloc();
while (!m_exit) {
m_mutex.lock();
if (m_packets.empty()) {
m_mutex.unlock();
std::this_thread::sleep_for(5ms);
continue;
}
auto packet = m_packets.front();
m_packets.pop();
m_mutex.unlock();
auto ret = avcodec_send_packet(m_context, packet.get());
if (ret < 0) {
char buffer[AV_ERROR_MAX_STRING_SIZE] = {0};
av_strerror(ret, buffer, sizeof(buffer));
LOG(error) << "read failed: " << ret << ", " << buffer;
}
while (true) {
ret = avcodec_receive_frame(m_context, frame);
if (ret == AVERROR_EOF || ret == AVERROR(EAGAIN)) {
break;
} else if (ret < 0) {
char buffer[AV_ERROR_MAX_STRING_SIZE] = {0};
av_strerror(ret, buffer, sizeof(buffer));
LOG(error) << "read failed: " << ret << ", " << buffer;
break;
}
LOG(info) << "width: " << frame->width << ", height: " << frame->height << ", pts: " << frame->pts
<< ", pkt_dts:" << frame->pkt_dts;
av_frame_unref(frame);
}
}
av_frame_free(&frame);
}