зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1206568: P1. Ensure FFmpeg decoder is only accessed through the decoder's task queue. r=cpearce
Add strong assertion that it is indeed the case.
This commit is contained in:
Родитель
d9647c7d7e
Коммит
8283012c2a
|
@ -18,8 +18,7 @@ namespace mozilla
|
|||
FFmpegAudioDecoder<LIBAV_VER>::FFmpegAudioDecoder(
|
||||
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
||||
const AudioInfo& aConfig)
|
||||
: FFmpegDataDecoder(aTaskQueue, GetCodecId(aConfig.mMimeType))
|
||||
, mCallback(aCallback)
|
||||
: FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
{
|
||||
MOZ_COUNT_CTOR(FFmpegAudioDecoder);
|
||||
// Use a new MediaByteBuffer as the object will be modified during initialization.
|
||||
|
@ -85,6 +84,7 @@ CopyAndPackAudio(AVFrame* aFrame, uint32_t aNumChannels, uint32_t aNumAFrames)
|
|||
void
|
||||
FFmpegAudioDecoder<LIBAV_VER>::DecodePacket(MediaRawData* aSample)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
AVPacket packet;
|
||||
av_init_packet(&packet);
|
||||
|
||||
|
@ -160,12 +160,12 @@ FFmpegAudioDecoder<LIBAV_VER>::Input(MediaRawData* aSample)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FFmpegAudioDecoder<LIBAV_VER>::Drain()
|
||||
void
|
||||
FFmpegAudioDecoder<LIBAV_VER>::ProcessDrain()
|
||||
{
|
||||
mTaskQueue->AwaitIdle();
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
ProcessFlush();
|
||||
mCallback->DrainComplete();
|
||||
return Flush();
|
||||
}
|
||||
|
||||
AVCodecID
|
||||
|
|
|
@ -27,13 +27,11 @@ public:
|
|||
|
||||
virtual nsRefPtr<InitPromise> Init() override;
|
||||
virtual nsresult Input(MediaRawData* aSample) override;
|
||||
virtual nsresult Drain() override;
|
||||
virtual void ProcessDrain() override;
|
||||
static AVCodecID GetCodecId(const nsACString& aMimeType);
|
||||
|
||||
private:
|
||||
void DecodePacket(MediaRawData* aSample);
|
||||
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
|
|
@ -21,12 +21,16 @@ bool FFmpegDataDecoder<LIBAV_VER>::sFFmpegInitDone = false;
|
|||
StaticMutex FFmpegDataDecoder<LIBAV_VER>::sMonitor;
|
||||
|
||||
FFmpegDataDecoder<LIBAV_VER>::FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
AVCodecID aCodecID)
|
||||
: mTaskQueue(aTaskQueue)
|
||||
, mCallback(aCallback)
|
||||
, mCodecContext(nullptr)
|
||||
, mFrame(NULL)
|
||||
, mExtraData(nullptr)
|
||||
, mCodecID(aCodecID)
|
||||
, mMonitor("FFMpegaDataDecoder")
|
||||
, mIsFlushing(false)
|
||||
{
|
||||
MOZ_COUNT_CTOR(FFmpegDataDecoder);
|
||||
}
|
||||
|
@ -128,15 +132,58 @@ FFmpegDataDecoder<LIBAV_VER>::InitDecoder()
|
|||
}
|
||||
|
||||
nsresult
|
||||
FFmpegDataDecoder<LIBAV_VER>::Flush()
|
||||
FFmpegDataDecoder<LIBAV_VER>::Shutdown()
|
||||
{
|
||||
mTaskQueue->Flush();
|
||||
avcodec_flush_buffers(mCodecContext);
|
||||
if (mTaskQueue) {
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &FFmpegDataDecoder<LIBAV_VER>::ProcessShutdown);
|
||||
mTaskQueue->Dispatch(runnable.forget());
|
||||
} else {
|
||||
ProcessShutdown();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FFmpegDataDecoder<LIBAV_VER>::Shutdown()
|
||||
FFmpegDataDecoder<LIBAV_VER>::Flush()
|
||||
{
|
||||
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
|
||||
mIsFlushing = true;
|
||||
mTaskQueue->Flush();
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &FFmpegDataDecoder<LIBAV_VER>::ProcessFlush);
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mTaskQueue->Dispatch(runnable.forget());
|
||||
while (mIsFlushing) {
|
||||
mon.Wait();
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FFmpegDataDecoder<LIBAV_VER>::Drain()
|
||||
{
|
||||
MOZ_ASSERT(mCallback->OnReaderTaskQueue());
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
NS_NewRunnableMethod(this, &FFmpegDataDecoder<LIBAV_VER>::ProcessDrain);
|
||||
mTaskQueue->Dispatch(runnable.forget());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
FFmpegDataDecoder<LIBAV_VER>::ProcessFlush()
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
if (mCodecContext) {
|
||||
avcodec_flush_buffers(mCodecContext);
|
||||
}
|
||||
MonitorAutoLock mon(mMonitor);
|
||||
mIsFlushing = false;
|
||||
mon.NotifyAll();
|
||||
}
|
||||
|
||||
void
|
||||
FFmpegDataDecoder<LIBAV_VER>::ProcessShutdown()
|
||||
{
|
||||
StaticMutexAutoLock mon(sMonitor);
|
||||
|
||||
|
@ -152,12 +199,12 @@ FFmpegDataDecoder<LIBAV_VER>::Shutdown()
|
|||
mFrame = nullptr;
|
||||
#endif
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
AVFrame*
|
||||
FFmpegDataDecoder<LIBAV_VER>::PrepareFrame()
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
#if LIBAVCODEC_VERSION_MAJOR >= 55
|
||||
if (mFrame) {
|
||||
av_frame_unref(mFrame);
|
||||
|
|
|
@ -23,7 +23,9 @@ template <>
|
|||
class FFmpegDataDecoder<LIBAV_VER> : public MediaDataDecoder
|
||||
{
|
||||
public:
|
||||
FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue, AVCodecID aCodecID);
|
||||
FFmpegDataDecoder(FlushableTaskQueue* aTaskQueue,
|
||||
MediaDataDecoderCallback* aCallback,
|
||||
AVCodecID aCodecID);
|
||||
virtual ~FFmpegDataDecoder();
|
||||
|
||||
static bool Link();
|
||||
|
@ -31,19 +33,33 @@ public:
|
|||
virtual nsRefPtr<InitPromise> Init() override = 0;
|
||||
virtual nsresult Input(MediaRawData* aSample) override = 0;
|
||||
virtual nsresult Flush() override;
|
||||
virtual nsresult Drain() override = 0;
|
||||
virtual nsresult Drain() override;
|
||||
virtual nsresult Shutdown() override;
|
||||
|
||||
protected:
|
||||
// Flush and Drain operation, always run
|
||||
virtual void ProcessFlush();
|
||||
virtual void ProcessDrain() = 0;
|
||||
virtual void ProcessShutdown();
|
||||
AVFrame* PrepareFrame();
|
||||
nsresult InitDecoder();
|
||||
|
||||
FlushableTaskQueue* mTaskQueue;
|
||||
nsRefPtr<FlushableTaskQueue> mTaskQueue;
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
|
||||
AVCodecContext* mCodecContext;
|
||||
AVFrame* mFrame;
|
||||
nsRefPtr<MediaByteBuffer> mExtraData;
|
||||
AVCodecID mCodecID;
|
||||
|
||||
// For wait on mIsFlushing during Shutdown() process.
|
||||
// Protects mReorderQueue.
|
||||
Monitor mMonitor;
|
||||
// Set on reader/decode thread calling Flush() to indicate that output is
|
||||
// not required and so input samples on mTaskQueue need not be processed.
|
||||
// Cleared on mTaskQueue in ProcessDrain().
|
||||
Atomic<bool> mIsFlushing;
|
||||
|
||||
private:
|
||||
static bool sFFmpegInitDone;
|
||||
static StaticMutex sMonitor;
|
||||
|
|
|
@ -28,8 +28,7 @@ FFmpegH264Decoder<LIBAV_VER>::FFmpegH264Decoder(
|
|||
FlushableTaskQueue* aTaskQueue, MediaDataDecoderCallback* aCallback,
|
||||
const VideoInfo& aConfig,
|
||||
ImageContainer* aImageContainer)
|
||||
: FFmpegDataDecoder(aTaskQueue, GetCodecId(aConfig.mMimeType))
|
||||
, mCallback(aCallback)
|
||||
: FFmpegDataDecoder(aTaskQueue, aCallback, GetCodecId(aConfig.mMimeType))
|
||||
, mImageContainer(aImageContainer)
|
||||
, mDisplayWidth(aConfig.mDisplay.width)
|
||||
, mDisplayHeight(aConfig.mDisplay.height)
|
||||
|
@ -57,6 +56,7 @@ FFmpegH264Decoder<LIBAV_VER>::Init()
|
|||
int64_t
|
||||
FFmpegH264Decoder<LIBAV_VER>::GetPts(const AVPacket& packet)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
#if LIBAVCODEC_VERSION_MAJOR == 53
|
||||
if (mFrame->pkt_pts == 0) {
|
||||
return mFrame->pkt_dts;
|
||||
|
@ -71,6 +71,8 @@ FFmpegH264Decoder<LIBAV_VER>::GetPts(const AVPacket& packet)
|
|||
FFmpegH264Decoder<LIBAV_VER>::DecodeResult
|
||||
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
uint8_t* inputData = const_cast<uint8_t*>(aSample->Data());
|
||||
size_t inputSize = aSample->Size();
|
||||
|
||||
|
@ -122,6 +124,8 @@ FFmpegH264Decoder<LIBAV_VER>::DecodeResult
|
|||
FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
||||
uint8_t* aData, int aSize)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
AVPacket packet;
|
||||
av_init_packet(&packet);
|
||||
|
||||
|
@ -208,6 +212,8 @@ FFmpegH264Decoder<LIBAV_VER>::DoDecodeFrame(MediaRawData* aSample,
|
|||
void
|
||||
FFmpegH264Decoder<LIBAV_VER>::DecodeFrame(MediaRawData* aSample)
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
|
||||
if (DoDecodeFrame(aSample) != DecodeResult::DECODE_ERROR &&
|
||||
mTaskQueue->IsEmpty()) {
|
||||
mCallback->InputExhausted();
|
||||
|
@ -339,32 +345,15 @@ FFmpegH264Decoder<LIBAV_VER>::Input(MediaRawData* aSample)
|
|||
}
|
||||
|
||||
void
|
||||
FFmpegH264Decoder<LIBAV_VER>::DoDrain()
|
||||
FFmpegH264Decoder<LIBAV_VER>::ProcessDrain()
|
||||
{
|
||||
MOZ_ASSERT(mTaskQueue->IsCurrentThreadIn());
|
||||
nsRefPtr<MediaRawData> empty(new MediaRawData());
|
||||
while (DoDecodeFrame(empty) == DecodeResult::DECODE_FRAME) {
|
||||
}
|
||||
mCallback->DrainComplete();
|
||||
}
|
||||
|
||||
nsresult
|
||||
FFmpegH264Decoder<LIBAV_VER>::Drain()
|
||||
{
|
||||
nsCOMPtr<nsIRunnable> runnable(
|
||||
NS_NewRunnableMethod(this, &FFmpegH264Decoder<LIBAV_VER>::DoDrain));
|
||||
mTaskQueue->Dispatch(runnable.forget());
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
FFmpegH264Decoder<LIBAV_VER>::Flush()
|
||||
{
|
||||
nsresult rv = FFmpegDataDecoder::Flush();
|
||||
// Even if the above fails we may as well clear our frame queue.
|
||||
return rv;
|
||||
}
|
||||
|
||||
FFmpegH264Decoder<LIBAV_VER>::~FFmpegH264Decoder()
|
||||
{
|
||||
MOZ_COUNT_DTOR(FFmpegH264Decoder);
|
||||
|
|
|
@ -38,8 +38,7 @@ public:
|
|||
|
||||
virtual nsRefPtr<InitPromise> Init() override;
|
||||
virtual nsresult Input(MediaRawData* aSample) override;
|
||||
virtual nsresult Drain() override;
|
||||
virtual nsresult Flush() override;
|
||||
virtual void ProcessDrain() override;
|
||||
static AVCodecID GetCodecId(const nsACString& aMimeType);
|
||||
|
||||
private:
|
||||
|
@ -62,7 +61,6 @@ private:
|
|||
static void ReleaseBufferCb(AVCodecContext* aCodecContext, AVFrame* aFrame);
|
||||
int64_t GetPts(const AVPacket& packet);
|
||||
|
||||
MediaDataDecoderCallback* mCallback;
|
||||
nsRefPtr<ImageContainer> mImageContainer;
|
||||
uint32_t mDisplayWidth;
|
||||
uint32_t mDisplayHeight;
|
||||
|
|
Загрузка…
Ссылка в новой задаче