diff options
Diffstat (limited to 'rotord/libavwrapper.h')
| -rwxr-xr-x | rotord/libavwrapper.h | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/rotord/libavwrapper.h b/rotord/libavwrapper.h new file mode 100755 index 0000000..faa4a2e --- /dev/null +++ b/rotord/libavwrapper.h @@ -0,0 +1,274 @@ + #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 + +#ifndef UINT64_C +#define UINT64_C(c) (c ## ULL) +#endif + +#include "Poco/Mutex.h" + +extern "C" { +#include <libavcodec/avcodec.h> +#include <libavformat/avformat.h> +#include <libavutil/pixfmt.h> +#include <libavutil/opt.h> +#include <libavutil/imgutils.h> + +#include <libswscale/swscale.h> //? +} + +/* +#include <QFile> +#include <QNetworkAccessManager> +#include <QMutex> +#include <QUrl> +#include <QBuffer> +*/ + + +#include <string> +#include <stdexcept> +#include <iostream> +#include <fstream> +#include <math.h> +#include <vector> + + + +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); + uint8_t getPixelIntensity(int x, int y, Channel c = GRAY) const; + bool fetchFrame(int targetFrameIndex = 0); + int getNumberOfFrames() const; + int getWidth() const; + int getHeight() const; + int getNumberOfChannels() const; + bool readNextFrame(int targetFrameIndex = 0); + bool readNextFrameWithPacket(int targetFrameIndex, AVPacket& packet, AVFrame* pYuv); + int seekToFrame(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 + + // For loading from URL + /* + static const int ioBufferSize = 32768; + unsigned char * ioBuffer; + QNetworkAccessManager networkManager; + AVIOContext* avioContext; + QFile fileStream; + QNetworkReply* reply; + QBuffer fileBuffer; + QByteArray byteArray; + */ + }; + + + // 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: + virtual ~exporter(){}; + 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); + 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<uint16_t> buffer; + AVFrame* frame; + + AVStream* audioStream; + + AVPacket packet; + int sample_end; + int sample_start; + + }; + +} + + + +#endif // libavwrapper_H |
