#ifndef libavwrapper_H #define libavwrapper_H /* * libavwrapper.h * May 2012 Christopher Bruns * The libavwrapper class is a C++ wrapper around the poorly documented * libavcodec movie API used by ffmpeg. I made extensive use of Nathan * Clack's implemention in the whisk project. * * The libavwrapper.h and libavwrapper.cpp files depend only on the libavcodec * and allied sets of libraries. To compartmentalize and reduce dependencies * I placed the Vaa3d specific use of this class into a separate set of * source files: loadV3dFFMpeg.h/cpp */ //////////////////////// //now that we have guards //instead of crashing instantly when the 2nd thread tries to encode a frame, we get an error //*** Error in `./rotord': corrupted double-linked list: 0x00007f3c31b1b630 *** //or //*** Error in `./rotord': double free or corruption (out): 0x00007f3bf8210080 *** /////////////////////// //http://blog.tomaka17.com/2012/03/libavcodeclibavformat-tutorial/ //great to use c++11 features //http://dranger.com/ffmpeg/ //the mnost up to date tutorial? //https://github.com/lbrandy/ffmpeg-fas/tree/master //try this! #ifndef UINT64_C #define UINT64_C(c) (c ## ULL) #endif #include "Poco/Mutex.h" extern "C" { #include #include #include #include //#include //#include #include //? } /* #include #include #include #include #include */ #include #include #include #include #include #include namespace libav { static bool b_is_one_time_inited=false; // Some libavcodec calls are not reentrant void maybeInitFFMpegLib(); static int sws_flags = SWS_BICUBIC; // Translated to C++ by Christopher Bruns May 2012 // from ffmeg_adapt.c in whisk package by Nathan Clack, Mark Bolstadt, Michael Meeuwisse class decoder { public: enum Channel { RED = 0, GRAY = 0, GREEN = 1, BLUE = 2, ALPHA = 3 }; decoder(PixelFormat pixelFormat=PIX_FMT_RGB24); //decoder(QUrl url, PixelFormat pixelFormat=PIX_FMT_RGB24); void cleanup(); virtual ~decoder(); //bool open(QUrl url, enum PixelFormat formatParam = PIX_FMT_RGB24); //bool open(QIODevice& fileStream, QString& fileName, enum PixelFormat formatParam = PIX_FMT_RGB24); bool reinit_buffers_and_scaler(); bool init_buffers_and_scaler(); uint8_t getPixelIntensity(int x, int y, Channel c = GRAY) const; bool fetchFrame(int targetFrameIndex = 0); bool fetchFrame(int w,int h,int targetFrameIndex = 0); int getNumberOfFrames() const; int getWidth() const; int getHeight() const; float getFrameRate() const{return framerate;}; int getNumberOfChannels() const; bool readNextFrame(int targetFrameIndex = 0); bool readNextFrameWithPacket(int targetFrameIndex, AVPacket& packet, AVFrame* pYuv); int seekToFrame(int targetFrameIndex = 0); int seekToFrameNew(int targetFrameIndex = 0); // make certain members public, for use by Fast3DTexture class AVFrame *pFrameRGB; AVFrame *pRaw; AVFormatContext *container; AVCodecContext *pCtx; int videoStream; int previousFrameIndex; bool isOpen; bool open(std::string& fileName, enum PixelFormat formatParam = PIX_FMT_RGB24); bool open(char* fileName, enum PixelFormat formatParam = PIX_FMT_RGB24); protected: void initialize(); bool openUsingInitializedContainer(enum PixelFormat formatParam = PIX_FMT_RGB24 ); static bool avtry(int result, const std::string& msg); AVCodec *pCodec; uint8_t *buffer, *blank; //struct SwsContext *Sctx; int width, height; PixelFormat format; size_t numBytes; int numFrames; int sc; // number of color channels float framerate; //NB representing framerate as a float implies that //ABOVE ~93 HOURS AT 25FPS the calculations will be inaccurate }; /* // TODO - finish refactoring based on // http://svn.gnumonks.org/trunk/21c3-video/ffmpeg/ffmpeg-0.4.9-pre1/output_example.c class encoder { public: //typedef encoder::Channel Channel; encoder(const char * file_name, int width, int height, float _framerate=25.0f, enum AVCodecID codec_id = CODEC_ID_H264); virtual ~encoder(); void setPixelIntensity(int x, int y, int c, uint8_t value); void write_frame(float seconds,uint8_t *rgbdata); void write_frame(float seconds,uint16_t *audiodata); int get_audio_framesize(){ return audio_input_frame_size; } float get_audio_step(){return audiostep;}; protected: AVFormatContext *container; AVCodecContext *pCtx; AVFrame *picture_yuv; AVFrame *picture_rgb; AVFrame *audio_frame; float timebase; struct SwsContext *Sctx; AVStream *audio_st; AVStream *video_st; AVCodecContext *aCtx; int audio_input_frame_size; float audiostep; }; */ class exporter { public: exporter(){ sws_ctx = NULL; } virtual ~exporter(){ if (NULL != sws_ctx) { sws_freeContext(sws_ctx); sws_ctx = NULL; } }; bool setup(int w,int h, int bitRate, int frameRate, std::string container); bool record(std::string filename); bool encodeFrame(unsigned char *pixels, uint16_t *samples); bool encodeFrame(unsigned char *pixels,AVPacket *audiopkt); //is possible to just copy the packets? bool encodeFrame(unsigned char *pixels); bool encodeFrame(uint16_t *samples); void finishRecord(); int get_audio_framesize(){return audioframesize;}; float get_audio_step(){return audiostep;}; AVStream *add_stream(AVFormatContext *oc, AVCodec **codec,enum AVCodecID codec_id); //AVCodecID void open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st); int open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st); void write_audio_frame(AVFormatContext *oc, AVStream *st,uint16_t *samples); void write_audio_frame(AVFormatContext *oc, AVStream *st,AVPacket *pkt); void close_audio(AVFormatContext *oc, AVStream *st); void write_video_frame(AVFormatContext *oc, AVStream *st, uint8_t *pixels); void close_video(AVFormatContext *oc, AVStream *st); private: AVOutputFormat *fmt; AVFormatContext *oc; AVStream *audio_st, *video_st; AVCodec *audio_codec, *video_codec; double audio_pts, video_pts; struct SwsContext *sws_ctx; int audioframesize; float audiostep; int w; int h; int bitRate; int frameRate; std::string container; int outputframe; // video output // AVFrame *frame; AVPicture src_picture, dst_picture; int frame_count; uint8_t *outPixels; //************************************************************// // audio output // float t, tincr, tincr2; int audio_input_frame_size; }; class audioloader{ public: audioloader(){ready=false;sample_start=0;sample_end=0;}; bool setup(const std::string &filename); AVFrame* get_frame(); uint16_t* get_samples(int num); AVPacket* get_packet(); bool close(); bool ready; AVCodecContext* codecContext; AVFormatContext* formatContext; int channels; //necessary to handle final packet -- unititialised after load/ problem? private: std::vector buffer; AVFrame* frame; AVStream* audioStream; AVPacket packet; int sample_end; int sample_start; bool isPlanar; }; } #endif // libavwrapper_H