root/src/add-ons/media/plugins/ffmpeg/AVCodecDecoder.h
/*
 * 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