61 lines
2.0 KiB
C++
61 lines
2.0 KiB
C++
#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);
|
|
}
|