70 lines
1.7 KiB
C++
70 lines
1.7 KiB
C++
#include "ffmpegvideodecoder.h"
|
|
|
|
#include <QDebug>
|
|
|
|
FFmpegVideoDecoder::FFmpegVideoDecoder()
|
|
{
|
|
|
|
}
|
|
|
|
FramePtr FFmpegVideoDecoder::Retrieve(const rational &timecode, const rational &length)
|
|
{
|
|
if (!open_ && !Open()) {
|
|
qWarning() << "Failed to open FFmpeg stream";
|
|
return nullptr;
|
|
}
|
|
|
|
|
|
|
|
// TODO index frames
|
|
|
|
int receive_ret;
|
|
|
|
// Allocate new frame
|
|
AVFrame* frame = av_frame_alloc();
|
|
AVPacket* pkt = av_packet_alloc();
|
|
|
|
while ((receive_ret = avcodec_receive_frame(codec_ctx_, frame)) == AVERROR(EAGAIN)) {
|
|
int read_ret = 0;
|
|
do {
|
|
|
|
// Make sure any previous packet buffers are cleared before reading new ones
|
|
av_packet_unref(pkt);
|
|
|
|
// Read next packet from file
|
|
read_ret = av_read_frame(fmt_ctx_, pkt);
|
|
|
|
} while (read_ret >= 0 && pkt->stream_index != stream()->file_index);
|
|
|
|
if (read_ret >= 0) {
|
|
int send_ret = avcodec_send_packet(codec_ctx_, pkt);
|
|
if (send_ret < 0) {
|
|
qCritical() << "Failed to send packet to decoder." << send_ret;
|
|
return nullptr;
|
|
}
|
|
} else {
|
|
if (read_ret == AVERROR_EOF) {
|
|
int send_ret = avcodec_send_packet(codec_ctx_, nullptr);
|
|
if (send_ret < 0) {
|
|
qCritical() << "Failed to send packet to decoder." << send_ret;
|
|
return nullptr;
|
|
}
|
|
} else {
|
|
qCritical() << "Could not read frame." << read_ret;
|
|
return nullptr;
|
|
}
|
|
}
|
|
}
|
|
if (receive_ret < 0) {
|
|
if (receive_ret != AVERROR_EOF) {
|
|
qCritical() << "Failed to receive packet from decoder." << receive_ret;
|
|
}
|
|
}
|
|
|
|
// Free AVPacket
|
|
av_packet_free(&pkt);
|
|
|
|
// AVFrame is wrapped in Frame object and shared ptr to automatically clear it
|
|
return std::make_shared<Frame>(frame);
|
|
}
|