parent
4c7a513b2d
commit
17c770de6f
@ -0,0 +1,117 @@
|
||||
#include "frames.h"
|
||||
extern "C"
|
||||
{
|
||||
#include "libavutil/avutil.h"
|
||||
#include "libavformat/avformat.h"
|
||||
}
|
||||
|
||||
Frames::Frames()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
Frames::~Frames()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
bool Frames::init()
|
||||
{
|
||||
m_decodingFrame = av_frame_alloc();
|
||||
if (!m_decodingFrame) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
m_renderingframe = av_frame_alloc();
|
||||
if (!m_renderingframe) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
// there is initially no rendering frame, so consider it has already been
|
||||
// consumed
|
||||
m_renderingFrameConsumed = true;
|
||||
return true;
|
||||
|
||||
error:
|
||||
deInit();
|
||||
return false;
|
||||
}
|
||||
|
||||
void Frames::deInit()
|
||||
{
|
||||
if (m_decodingFrame) {
|
||||
av_frame_free(&m_decodingFrame);
|
||||
m_decodingFrame = Q_NULLPTR;
|
||||
}
|
||||
if (m_renderingframe) {
|
||||
av_frame_free(&m_renderingframe);
|
||||
m_renderingframe = Q_NULLPTR;
|
||||
}
|
||||
}
|
||||
|
||||
void Frames::lock()
|
||||
{
|
||||
m_mutex.lock();
|
||||
}
|
||||
|
||||
void Frames::unLock()
|
||||
{
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
AVFrame *Frames::decodingFrame()
|
||||
{
|
||||
return m_decodingFrame;
|
||||
}
|
||||
|
||||
bool Frames::offerDecodedFrame()
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
#ifndef SKIP_FRAMES
|
||||
// if SKIP_FRAMES is disabled, then the decoder must wait for the current
|
||||
// frame to be consumed
|
||||
while (!m_renderingFrameConsumed && !m_stopped) {
|
||||
m_renderingFrameConsumedCond.wait(&m_mutex);
|
||||
}
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
swap();
|
||||
bool previousFrameConsumed = m_renderingFrameConsumed;
|
||||
m_renderingFrameConsumed = false;
|
||||
m_mutex.unlock();
|
||||
return previousFrameConsumed;
|
||||
}
|
||||
|
||||
const AVFrame *Frames::consumeRenderedFrame()
|
||||
{
|
||||
Q_ASSERT(!m_renderingFrameConsumed);
|
||||
m_renderingFrameConsumed = true;
|
||||
|
||||
#ifndef SKIP_FRAMES
|
||||
// if SKIP_FRAMES is disabled, then notify the decoder the current frame is
|
||||
// consumed, so that it may push a new one
|
||||
m_renderingFrameConsumedCond.wakeOne();
|
||||
#endif
|
||||
return m_renderingframe;
|
||||
}
|
||||
|
||||
void Frames::stop()
|
||||
{
|
||||
#ifndef SKIP_FRAMES
|
||||
m_mutex.lock();
|
||||
m_stopped = true;
|
||||
m_mutex.unlock();
|
||||
// wake up blocking wait
|
||||
m_renderingFrameConsumedCond.wakeOne();
|
||||
#endif
|
||||
}
|
||||
|
||||
void Frames::swap()
|
||||
{
|
||||
AVFrame *tmp = m_decodingFrame;
|
||||
m_decodingFrame = m_renderingframe;
|
||||
m_renderingframe = tmp;
|
||||
}
|
||||
@ -0,0 +1,50 @@
|
||||
#ifndef FRAMES_H
|
||||
#define FRAMES_H
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
|
||||
// forward declarations
|
||||
typedef struct AVFrame AVFrame;
|
||||
|
||||
class Frames
|
||||
{
|
||||
public:
|
||||
Frames();
|
||||
virtual ~Frames();
|
||||
|
||||
bool init();
|
||||
void deInit();
|
||||
void lock();
|
||||
void unLock();
|
||||
|
||||
AVFrame* decodingFrame();
|
||||
// set the decoder frame as ready for rendering
|
||||
// this function locks m_mutex during its execution
|
||||
// returns true if the previous frame had been consumed
|
||||
bool offerDecodedFrame();
|
||||
|
||||
// mark the rendering frame as consumed and return it
|
||||
// MUST be called with m_mutex locked!!!
|
||||
// the caller is expected to render the returned frame to some texture before
|
||||
// unlocking m_mutex
|
||||
const AVFrame* consumeRenderedFrame();
|
||||
|
||||
// wake up and avoid any blocking call
|
||||
void stop();
|
||||
|
||||
private:
|
||||
void swap();
|
||||
|
||||
private:
|
||||
AVFrame* m_decodingFrame = Q_NULLPTR;
|
||||
AVFrame* m_renderingframe = Q_NULLPTR;
|
||||
QMutex m_mutex;
|
||||
bool m_renderingFrameConsumed = true;
|
||||
|
||||
#ifndef SKIP_FRAMES
|
||||
QWaitCondition m_renderingFrameConsumedCond;
|
||||
bool m_stopped = true;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif // FRAMES_H
|
||||
Loading…
Reference in new issue