274 changes: 141 additions & 133 deletions mythtv/libs/libmythtv/avformatdecoder.cpp

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion mythtv/libs/libmythtv/avformatdecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ class AvFormatDecoder : public DecoderBase
void SeekReset(long long, uint skipFrames, bool doFlush, bool discardFrames);

inline bool DecoderWillDownmix(const AVCodecContext *ctx);
bool DoPassThrough(const AVCodecContext *ctx, bool withProfile=true);
bool DoPassThrough(const AVCodecParameters *ctx, bool withProfile=true);
bool SetupAudioStream(void);
void SetupAudioStreamSubIndexes(int streamIndex);
void RemoveAudioStreams();
Expand Down
66 changes: 66 additions & 0 deletions mythtv/libs/libmythtv/mythavutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ extern "C" {
#include "libavfilter/buffersrc.h"
#include "libavfilter/buffersink.h"
#include "libavutil/imgutils.h"
#include "libavformat/avformat.h"
}
#include <QMutexLocker>

AVPixelFormat FrameTypeToPixelFormat(VideoFrameType type)
{
Expand Down Expand Up @@ -374,3 +376,67 @@ MythPictureDeinterlacer::~MythPictureDeinterlacer()
avfilter_graph_free(&m_filter_graph);
}
}


MythCodecMap *gCodecMap = new MythCodecMap();

MythCodecMap::MythCodecMap() : mapLock(QMutex::Recursive)
{
}

MythCodecMap::~MythCodecMap()
{
freeAllCodecContexts();
}

AVCodecContext *MythCodecMap::getCodecContext(const AVStream *stream, const AVCodec *pCodec)
{
QMutexLocker lock(&mapLock);
AVCodecContext *avctx = streamMap.value(stream, NULL);
if (!avctx)
{
if (stream == NULL || stream->codecpar == NULL)
return NULL;
if (!pCodec)
pCodec = avcodec_find_decoder(stream->codecpar->codec_id);
if (!pCodec)
{
LOG(VB_GENERAL, LOG_WARNING,
QString("avcodec_find_decoder fail for %1").arg(stream->codecpar->codec_id));
return NULL;
}
avctx = avcodec_alloc_context3(pCodec);
if (avcodec_parameters_to_context(avctx, stream->codecpar) != NULL)
avcodec_free_context(&avctx);
if (avctx)
{
av_codec_set_pkt_timebase(avctx, stream->time_base);
streamMap.insert(stream, avctx);
}
}
return avctx;
}

AVCodecContext *MythCodecMap::hasCodecContext(const AVStream *stream)
{
return streamMap.value(stream, NULL);
}

void MythCodecMap::freeCodecContext(const AVStream *stream)
{
QMutexLocker lock(&mapLock);
AVCodecContext *avctx = streamMap.take(stream);
if (avctx)
avcodec_free_context(&avctx);
}

void MythCodecMap::freeAllCodecContexts()
{
QMutexLocker lock(&mapLock);
QMap<const AVStream*, AVCodecContext*>::iterator i = streamMap.begin();
while (i != streamMap.end()) {
const AVStream *stream = i.key();
++i;
freeCodecContext(stream);
}
}
34 changes: 34 additions & 0 deletions mythtv/libs/libmythtv/mythavutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,13 @@ extern "C" {
#include "libavcodec/avcodec.h"
}

#include <QMap>
#include <QMutex>

struct AVFilterGraph;
struct AVFilterContext;
struct AVStream;
struct AVCodecContext;

/** MythAVFrame
* little utility class that act as a safe way to allocate an AVFrame
Expand Down Expand Up @@ -71,6 +76,35 @@ class MythAVFrame
AVFrame *m_frame;
};

/**
* MythCodecMap
* Utility class that keeps pointers to
* an AVStream and its AVCodecContext. The codec member
* of AVStream was previously used for this but is now
* deprecated.
*
* This is a singeton class - only 1 instance gets created.
*/

class MythCodecMap
{
public:
MythCodecMap();
~MythCodecMap();
static MythCodecMap *getInstance();
AVCodecContext *getCodecContext(const AVStream*, const AVCodec *pCodec = NULL);
AVCodecContext *hasCodecContext(const AVStream*);
void freeCodecContext(const AVStream*);
void freeAllCodecContexts();
protected:
QMap<const AVStream*, AVCodecContext*> streamMap;
QMutex mapLock;
};

/// This global variable contains the MythCodecMap instance for the app
extern MythCodecMap *gCodecMap;


class MythAVCopyPrivate;

/**
Expand Down
9 changes: 6 additions & 3 deletions mythtv/libs/libmythtv/privatedecoder_omx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ extern "C" {
#include "mythcorecontext.h"
#include "mythlogging.h"
#include "omxcontext.h"
#include "mythavutil.h"

using namespace omxcontext;


Expand Down Expand Up @@ -782,7 +784,8 @@ int PrivateDecoderOMX::GetFrame(
*got_picture_ptr = 1;

// Check for OMX_EventPortSettingsChanged notification
if (SettingsChanged(stream->codec) != OMX_ErrorNone)
AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
if (SettingsChanged(avctx) != OMX_ErrorNone)
{
// PGB If there was an error, discard this packet
*got_picture_ptr = 0;
Expand Down Expand Up @@ -815,7 +818,7 @@ int PrivateDecoderOMX::ProcessPacket(AVStream *stream, AVPacket *pkt)
// Convert h264_mp4toannexb
if (m_filter)
{
AVCodecContext *avctx = stream->codec;
AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
int outbuf_size = 0;
uint8_t *outbuf = NULL;
int res = av_bitstream_filter_filter(m_filter, avctx, NULL, &outbuf,
Expand Down Expand Up @@ -906,7 +909,7 @@ int PrivateDecoderOMX::GetBufferedFrame(AVStream *stream, AVFrame *picture)
if (!picture)
return -1;

AVCodecContext *avctx = stream->codec;
AVCodecContext *avctx = gCodecMap->getCodecContext(stream);
if (!avctx)
return -1;

Expand Down