⛏️ index : haiku.git

/*
 * Copyright (C) 2001 Carlos Hasan.
 * Copyright (C) 2001 FranΓ§ois Revol.
 * Copyright (C) 2001 Axel DΓΆrfler.
 * Copyright (C) 2004 Marcus Overhagen.
 * Copyright (C) 2009 Stephan Aßmus <superstippi@gmx.de>.
 * Copyright (C) 2015 Adrien Destugues <pulkomandy@pulkomandy.tk>.
 *
 * All rights reserved. Distributed under the terms of the MIT License.
 */
#ifndef AVCODEC_DECODER_H
#define AVCODEC_DECODER_H

//! libavcodec based decoder for Haiku


#include <MediaFormats.h>


extern "C" {
	#include "avcodec.h"
	#include "avfilter.h"
	#include "buffersink.h"
	#include "buffersrc.h"
	#include "imgutils.h"
	#include "swresample.h"
	#include "swscale.h"
	#include "timestamp.h"
}


#include "DecoderPlugin.h"
#include "ReaderPlugin.h"

#include "CodecTable.h"
#include "gfx_util.h"


#if 1
#define USE_SWS_FOR_COLOR_SPACE_CONVERSION 1
#else
#define USE_SWS_FOR_COLOR_SPACE_CONVERSION 0
// NOTE: David's color space conversion is much faster than the FFmpeg
// version. Perhaps the SWS code can be used for unsupported conversions?
// Otherwise the alternative code could simply be removed from this file.
#endif


class AVCodecDecoder : public Decoder {
public:
						AVCodecDecoder();

	virtual				~AVCodecDecoder();

	virtual	void		GetCodecInfo(media_codec_info* mci);

	virtual	status_t	Setup(media_format* ioEncodedFormat,
							const void* infoBuffer, size_t infoSize);

	virtual	status_t	NegotiateOutputFormat(media_format* inOutFormat);

	virtual	status_t	Decode(void* outBuffer, int64* outFrameCount,
							media_header* mediaHeader,
							media_decode_info* info);

	virtual	status_t	SeekedTo(int64 trame, bigtime_t time);


private:
			void		_ResetTempPacket();

			status_t	_NegotiateAudioOutputFormat(media_format* inOutFormat);

			status_t	_NegotiateVideoOutputFormat(media_format* inOutFormat);

			status_t	_DecodeAudio(void* outBuffer, int64* outFrameCount,
							media_header* mediaHeader,
							media_decode_info* info);

			status_t	_DecodeVideo(void* outBuffer, int64* outFrameCount,
							media_header* mediaHeader,
							media_decode_info* info);

			status_t	_DecodeNextAudioFrame();
			void		_ApplyEssentialAudioContainerPropertiesToContext();
			status_t	_ResetRawDecodedAudio();
			void		_CheckAndFixConditionsThatHintAtBrokenAudioCodeBelow();
			void		_MoveAudioFramesToRawDecodedAudioAndUpdateStartTimes();
			status_t	_DecodeNextAudioFrameChunk();
			status_t	_DecodeSomeAudioFramesIntoEmptyDecodedDataBuffer();
			void		_UpdateMediaHeaderForAudioFrame();

			status_t	_DecodeNextVideoFrame();
			void		_ApplyEssentialVideoContainerPropertiesToContext();
			status_t	_LoadNextChunkIfNeededAndAssignStartTime();
			status_t	_CopyChunkToChunkBufferAndAddPadding(const void* chunk,
							size_t chunkSize);
			status_t	_HandleNewVideoFrameAndUpdateSystemState();
			status_t	_FlushOneVideoFrameFromDecoderBuffer();
			void		_UpdateMediaHeaderForVideoFrame();
			status_t	_DeinterlaceAndColorConvertVideoFrame();

			// video deinterlace filter graph
			status_t	_InitFilterGraph(enum AVPixelFormat pixfmt,
							int32 width, int32 height);
			status_t	_ProcessFilterGraph(AVFrame *dst,
							const AVFrame *src, enum AVPixelFormat pixfmt,
							int32 width, int32 height);

			media_header		fHeader;
									// Contains the properties of the current
									// decoded audio / video frame

			media_format		fInputFormat;

			int64				fFrame;
			bool				fIsAudio;

			// FFmpeg related members
			const AVCodec*		fCodec;
			AVCodecContext*		fCodecContext;
			SwrContext*			fResampleContext;
			uint8_t*			fDecodedData;
			size_t				fDecodedDataSizeInBytes;
			AVFrame*			fPostProcessedDecodedPicture;
			AVFrame*			fRawDecodedPicture;
			AVFrame*			fRawDecodedAudio;

			bool 				fCodecInitDone;

			gfx_convert_func	fFormatConversionFunc;
#if USE_SWS_FOR_COLOR_SPACE_CONVERSION
			SwsContext*			fSwsContext;
#endif

			char*				fExtraData;
			int					fExtraDataSize;
			int					fBlockAlign;

			color_space			fOutputColorSpace;
			int32				fOutputFrameCount;
			float				fOutputFrameRate;
									// only for audio streams
			int					fOutputFrameSize;
									// sample size * channel count
			int					fInputFrameSize;
									// sample size * channel count
									// or just sample size for planar formats

			uint8_t*			fChunkBuffer;
			size_t				fChunkBufferSize;
			bool				fAudioDecodeError;

			AVFrame*			fDecodedDataBuffer;
			int32				fDecodedDataBufferOffset;
			int32				fDecodedDataBufferSize;

			AVPacket*			fTempPacket;

			// video deinterlace feature
			AVFilterContext*	fBufferSinkContext;
			AVFilterContext*	fBufferSourceContext;
			AVFilterGraph*		fFilterGraph;
			AVFrame*			fFilterFrame;
			int32				fLastWidth;
			int32				fLastHeight;
			enum AVPixelFormat	fLastPixfmt;
};

#endif // AVCODEC_DECODER_H