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