From 78eb4c35ae7ee52615c62abb3683595fe6384206 Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Wed, 12 Jun 2013 17:03:42 +0100 Subject: file clean --- rotord/libav/libavwrapper.cpp | 1573 ------------------------------------ rotord/libav/libavwrapper.h | 248 ------ rotord/libavaudioloader.cpp | 231 ------ rotord/libavaudioloader.h | 41 - rotord/libavwrapper_guarded.cpp | 1694 --------------------------------------- rotord/libavwrapper_guarded.h | 274 ------- rotord/rotord.cpp | 28 +- rotord/rotord.h | 41 + 8 files changed, 46 insertions(+), 4084 deletions(-) delete mode 100755 rotord/libav/libavwrapper.cpp delete mode 100755 rotord/libav/libavwrapper.h delete mode 100644 rotord/libavaudioloader.cpp delete mode 100644 rotord/libavaudioloader.h delete mode 100755 rotord/libavwrapper_guarded.cpp delete mode 100755 rotord/libavwrapper_guarded.h diff --git a/rotord/libav/libavwrapper.cpp b/rotord/libav/libavwrapper.cpp deleted file mode 100755 index 26b8b5a..0000000 --- a/rotord/libav/libavwrapper.cpp +++ /dev/null @@ -1,1573 +0,0 @@ -#include "libavwrapper.h" - - -extern "C" -{ -#include -} - -/* -#include -#include -#include -#include -#include -#include -*/ - -#include -#include -#include - -using namespace std; - -// Translated to C++ by Christopher Bruns May 2012 -// from ffmeg_adapt.c in whisk package by Nathan Clack, Mark Bolstadt, Michael Meeuwisse - -//QMutex decoder::mutex; - -// Avoid link error on some macs -#ifdef __APPLE__ -extern "C" { -#include -#include -// #include "compiler/compiler.h" - -/* - * Darwin doesn't have posix_memalign(), provide a private - * weak alternative - */ - /* -int __weak posix_memalign(void **ptr, size_t align, size_t size) -{ - if (*ptr) - return 0; - - return ENOMEM; -} -*/ -} -#endif - -// Custom read function so FFMPEG does not need to read from a local file by name. -// But rather from a stream derived from a URL or whatever. -extern "C" { - -int readFunction(void* opaque, uint8_t* buf, int buf_size) -{ - //QIODevice* stream = (QIODevice*)opaque; - ifstream* stream = (ifstream*)opaque; - //int numBytes = - stream->read((char*)buf, (streamsize)buf_size); - return stream->gcount(); //?? is this right - //numBytes; //TODO work out -} - -// http://cdry.wordpress.com/2009/09/09/using-custom-io-callbacks-with-ffmpeg/ -int64_t seekFunction(void* opaque, int64_t offset, int whence) -{ - //QIODevice* stream = (QIODevice*)opaque; - ifstream* stream = (ifstream*)opaque; - if (stream == NULL) - return -1; - else if (whence == AVSEEK_SIZE) - return -1; // "size of my handle in bytes" - //else if (stream->isSequential()) - // return -1; // cannot seek a sequential stream //presume this would be certain kind of network stream - else if (whence == SEEK_CUR) { // relative to start of file - if (! stream->seekg(offset,ios_base::cur)) //stream->pos() + offset) ) - return -1; - } - else if (whence == SEEK_END) { // relative to end of file - assert(offset < 0); - if (! stream->seekg(offset,ios_base::end)) //stream->size() + offset) ) - return -1; - } - else if (whence == SEEK_SET) { // relative to start of file - if (! stream->seekg(offset) ) - return -1; - } - else { - assert(false); - } - return stream->tellg(); -} - -} - - -///////////////////////////// -// AVPacketWrapper methods // -///////////////////////////// - - -class AVPacketWrapper -{ -public: - AVPacketWrapper(); - virtual ~AVPacketWrapper(); - void free(); - - AVPacket packet; -}; - - -AVPacketWrapper::AVPacketWrapper() -{ - packet.destruct = NULL; -} - -/* virtual */ -AVPacketWrapper::~AVPacketWrapper() -{ - free(); -} - -void AVPacketWrapper::free() -{ - av_free_packet(&packet); -} - - -//bool libav::b_is_one_time_inited = false; - -///////////////////////// -// decoder methods // -///////////////////////// - -libav::decoder::decoder(PixelFormat pixelFormat) - : isOpen(false) -{ - initialize(); - format = pixelFormat; -} - -/* -decoder::decoder(QUrl url, PixelFormat pixelFormat) - : isOpen(false) -{ - //QMutexLocker lock(&decoder::mutex); - initialize(); - format = pixelFormat; - isOpen = open(url, pixelFormat); -} -*/ - -/* virtual */ -libav::decoder::~decoder() -{ - //QMutexLocker lock(&decoder::mutex); - if (NULL != Sctx) { - sws_freeContext(Sctx); - Sctx = NULL; - } - if (NULL != pRaw) { - av_free(pRaw); - pRaw = NULL; - } - if (NULL != pFrameRGB) { - av_free(pFrameRGB); - pFrameRGB = NULL; - } - if (NULL != pCtx) { - avcodec_close(pCtx); - pCtx = NULL; - } - if (NULL != container) { - avformat_close_input(&container); - container = NULL; - } - if (NULL != buffer) { - av_free(buffer); - buffer = NULL; - } - if (NULL != blank) { - av_free(blank); - blank = NULL; - } - /* - if (NULL != avioContext) { - av_free(avioContext); - avioContext = NULL; - } - */ - //QNetworkreply - //if (reply != NULL) { - // reply->deleteLater(); - // reply = NULL; - //} - // Don't need to free pCodec? -} -/* -bool decoder::open(QUrl url, enum PixelFormat formatParam) -{ - if (url.isEmpty()) - return false; - - // Is the movie source a local file? - if (url.host() == "localhost") - url.setHost(""); - QString fileName = url.toLocalFile(); - if ( (! fileName.isEmpty()) - && (QFileInfo(fileName).exists()) ) - { - // return open(fileName, formatParam); // for testing only - - // Yes, the source is a local file - fileStream.setFileName(fileName); - // qDebug() << fileName; - if (! fileStream.open(QIODevice::ReadOnly)) - return false; - return open(fileStream, fileName, formatParam); - } - - // ...No, the source is not a local file - if (url.host() == "") - url.setHost("localhost"); - fileName = url.path(); - - // http://stackoverflow.com/questions/9604633/reading-a-file-located-in-memory-with-libavformat - // Load from URL - QEventLoop loop; // for synchronous url fetch http://stackoverflow.com/questions/5486090/qnetworkreply-wait-for-finished - QObject::connect(&networkManager, SIGNAL(finished(QNetworkReply*)), - &loop, SLOT(quit())); - QNetworkRequest request = QNetworkRequest(url); - // qDebug() << "networkManager" << __FILE__ << __LINE__; - reply = networkManager.get(request); - loop.exec(); - if (reply->error() != QNetworkReply::NoError) { - // qDebug() << reply->error(); - reply->deleteLater(); - reply = NULL; - return false; - } - QIODevice * stream = reply; - // Mpeg needs seekable device, so create in-memory buffer if necessary - if (stream->isSequential()) { - byteArray = stream->readAll(); - fileBuffer.setBuffer(&byteArray); - fileBuffer.open(QIODevice::ReadOnly); - if (! fileBuffer.seek(0)) - return false; - stream = &fileBuffer; - assert(! stream->isSequential()); - } - bool result = open(*stream, fileName, formatParam); - return result; -} - -bool decoder::open(QIODevice& fileStream, QString& fileName, enum PixelFormat formatParam) -{ - // http://stackoverflow.com/questions/9604633/reading-a-file-located-in-memory-with-libavformat - // I think AVIOContext is the trick used to redivert the input stream - ioBuffer = (unsigned char *)av_malloc(ioBufferSize + FF_INPUT_BUFFER_PADDING_SIZE); // can get av_free()ed by libav - avioContext = avio_alloc_context(ioBuffer, ioBufferSize, 0, (void*)(&fileStream), &readFunction, NULL, &seekFunction); - container = avformat_alloc_context(); - container->pb = avioContext; - - // Open file, check usability - std::string fileNameStd = fileName.toStdString(); - if (!avtry( avformat_open_input(&container, fileNameStd.c_str(), NULL, NULL), fileNameStd )) - return false; - return openUsingInitializedContainer(formatParam); -} -*/ -// file name based method for historical continuity -bool libav::decoder::open(char* fileName, enum PixelFormat formatParam){ - - if (!avtry( avformat_open_input(&container, fileName, NULL, NULL), string(fileName) )) - return false; - return openUsingInitializedContainer(formatParam); -} -bool libav::decoder::open(string& fileName, enum PixelFormat formatParam) -{ - // Open file, check usability - - if (!avtry( avformat_open_input(&container, fileName.c_str(), NULL, NULL), fileName )) - return false; - return openUsingInitializedContainer(formatParam); -} - - -bool libav::decoder::openUsingInitializedContainer(enum PixelFormat formatParam) -{ - format = formatParam; - sc = getNumberOfChannels(); - - if (!avtry( avformat_find_stream_info(container, NULL), "Cannot find stream information." )) - return false; - if (!avtry( videoStream=av_find_best_stream(container, AVMEDIA_TYPE_VIDEO, -1, -1, &pCodec, 0), "Cannot find a video stream." )) - return false; - pCtx=container->streams[videoStream]->codec; - width = pCtx->width; - height = pCtx->height; - if (!avtry( avcodec_open2(pCtx, pCodec, NULL), "Cannot open video decoder." )) - return false; - - /* Frame rate fix for some codecs */ - if( pCtx->time_base.num > 1000 && pCtx->time_base.den == 1 ) - pCtx->time_base.den = 1000; - - /* Compute the total number of frames in the file */ - /* duration is in microsecs */ - numFrames = (int)(( container->duration / (double)AV_TIME_BASE ) * pCtx->time_base.den + 0.5); - - /* Get framebuffers */ - if (! (pRaw = avcodec_alloc_frame()) ) - throw std::runtime_error(""); - if (! (pFrameRGB = avcodec_alloc_frame()) ) - throw std::runtime_error(""); - - /* Create data buffer */ - if (format == PIX_FMT_NONE) { - numBytes = 0; - buffer = NULL; - blank = NULL; - pFrameRGB = NULL; - Sctx = NULL; - } - else { - numBytes = avpicture_get_size( format, pCtx->width, pCtx->height ); // RGB24 format - if (! (buffer = (uint8_t*)av_malloc(numBytes + FF_INPUT_BUFFER_PADDING_SIZE)) ) // RGB24 format - throw std::runtime_error(""); - if (! (blank = (uint8_t*)av_mallocz(avpicture_get_size(pCtx->pix_fmt,width,height))) ) // native codec format - throw std::runtime_error(""); - - /* Init buffers */ - avpicture_fill( (AVPicture * ) pFrameRGB, buffer, format, - pCtx->width, pCtx->height ); - - /* Init scale & convert */ - if (! (Sctx=sws_getContext( - pCtx->width, - pCtx->height, - pCtx->pix_fmt, - width, - height, - format, - SWS_POINT, // fastest? - NULL,NULL,NULL)) ) - throw std::runtime_error(""); - } - - /* Give some info on stderr about the file & stream */ - //dump_format(container, 0, fname, 0); - - previousFrameIndex = -1; - return true; -} - -bool libav::decoder::fetchFrame(int targetFrameIndex) -{ - if ((targetFrameIndex < 0) || (targetFrameIndex > numFrames)) - return false; - if (targetFrameIndex == (previousFrameIndex + 1)) { - if (! readNextFrame(targetFrameIndex)) - return false; - } - else { - int64_t response=seekToFrame(targetFrameIndex); - if (response < 0) - return false; - if (response!=targetFrameIndex){ - cerr<<"libav::decoder asked for "<streams[videoStream]->duration; - int64_t ts = av_rescale(duration,targetFrameIndex,numFrames); - int64_t tol = av_rescale(duration,1,2*numFrames); - if ( (targetFrameIndex < 0) || (targetFrameIndex >= numFrames) ) { - return -1; - } - int result = avformat_seek_file( container, //format context - videoStream,//stream id - 0, //min timestamp 0? - ts, //target timestamp - ts, //max timestamp - 0);//flags AVSEEK_FLAG_ANY //doesn't seem to work great - if (result < 0) - return -1; - - avcodec_flush_buffers(pCtx); - if (! readNextFrame(targetFrameIndex)) - return -1; - - return targetFrameIndex; -} - -bool libav::decoder::readNextFrame(int targetFrameIndex) -{ - AVPacket packet = {0}; - av_init_packet(&packet); - bool result = readNextFrameWithPacket(targetFrameIndex, packet, pRaw); - av_free_packet(&packet); - return result; -} - -// WARNING this method can raise an exception -bool libav::decoder::readNextFrameWithPacket(int targetFrameIndex, AVPacket& packet, AVFrame* pYuv) -{ - int finished = 0; - do { - finished = 0; - av_free_packet(&packet); - int result; - if (!avtry(av_read_frame( container, &packet ), "Failed to read frame")) - return false; // !!NOTE: see docs on packet.convergence_duration for proper seeking - if( packet.stream_index != videoStream ) /* Is it what we're trying to parse? */ - continue; - if (!avtry(avcodec_decode_video2( pCtx, pYuv, &finished, &packet ), "Failed to decode video")) - return false; - // handle odd cases and debug - if((pCtx->codec_id==CODEC_ID_RAWVIDEO) && !finished) - { - avpicture_fill( (AVPicture * ) pYuv, blank, pCtx->pix_fmt,width, height ); // set to blank frame - finished = 1; - } -#if 0 // very useful for debugging - cout << "Packet - pts:" << (int)packet.pts; - cout << " dts:" << (int)packet.dts; - cout << " - flag: " << packet.flags; - cout << " - finished: " << finished; - cout << " - Frame pts:" << (int)pYuv->pts; - cout << " " << (int)pYuv->best_effort_timestamp; - cout << endl; - /* printf("Packet - pts:%5d dts:%5d (%5d) - flag: %1d - finished: %3d - Frame pts:%5d %5d\n", - (int)packet.pts,(int)packet.dts, - packet.flags,finished, - (int)pYuv->pts,(int)pYuv->best_effort_timestamp); */ -#endif - if(!finished) { - if (packet.pts == AV_NOPTS_VALUE) - throw std::runtime_error(""); - if (packet.size == 0) // packet.size==0 usually means EOF - break; - } - } while ( (!finished) || (pYuv->best_effort_timestamp < targetFrameIndex)); - - av_free_packet(&packet); - - if (format != PIX_FMT_NONE) { - sws_scale(Sctx, // sws context - pYuv->data, // src slice - pYuv->linesize, // src stride - 0, // src slice origin y - pCtx->height, // src slice height - pFrameRGB->data, // dst - pFrameRGB->linesize ); // dst stride - } - - previousFrameIndex = targetFrameIndex; - return true; -} - -uint8_t libav::decoder::getPixelIntensity(int x, int y, Channel c) const -{ - return *(pFrameRGB->data[0] + y * pFrameRGB->linesize[0] + x * sc + c); -} - -int libav::decoder::getNumberOfFrames() const { return numFrames; } - -int libav::decoder::getWidth() const { return width; } - -int libav::decoder::getHeight() const { return height; } - -int libav::decoder::getNumberOfChannels() const -{ - switch(format) - { - case PIX_FMT_BGRA: - return 4; - break; - case PIX_FMT_RGB24: - return 3; - break; - case PIX_FMT_GRAY8: - return 1; - break; - default: - return 0; - break; - } - return 0; -} - -void libav::decoder::initialize() -{ - Sctx = NULL; - pRaw = NULL; - pFrameRGB = NULL; - pCtx = NULL; - container = NULL; - buffer = NULL; - blank = NULL; - pCodec = NULL; - format = PIX_FMT_NONE; - //network stuff - //reply = NULL; - //ioBuffer = NULL; - //avioContext = NULL; - maybeInitFFMpegLib(); -} - -void libav::maybeInitFFMpegLib() -{ - if (b_is_one_time_inited) - return; - av_register_all(); - avcodec_register_all(); - avformat_network_init(); - b_is_one_time_inited = true; -} - -bool libav::decoder::avtry(int result, const std::string& msg) { - if ((result < 0) && (result != AVERROR_EOF)) { - char buf[1024]; - av_strerror(result, buf, sizeof(buf)); - std::string message = std::string("libav::Error: ") + msg + buf; - //qDebug() << QString(message.c_str()); - cerr<oformat = fmt; - - fmt->video_codec = codec_id; - // fmt->video_codec = CODEC_ID_H264; // fails to write - - AVStream * video_st = avformat_new_stream(container, NULL); - - pCtx = video_st->codec; - pCtx->codec_id = fmt->video_codec; - pCtx->codec_type = AVMEDIA_TYPE_VIDEO; - // resolution must be a multiple of two - pCtx->width = width; - pCtx->height = height; - - // bit_rate determines image quality - pCtx->bit_rate = width * height * 4; // ? - // pCtx->qmax = 50; // no effect? - - // "high quality" parameters from http://www.cs.ait.ac.th/~on/mplayer/pl/menc-feat-enc-libavcodec.html - // vcodec=mpeg4:mbd=2:mv0:trell:v4mv:cbp:last_pred=3:predia=2:dia=2:vmax_b_frames=2:vb_strategy=1:precmp=2:cmp=2:subcmp=2:preme=2:vme=5:naq:qns=2 - if (false) // does not help - // if (pCtx->codec_id == CODEC_ID_MPEG4) - { - pCtx->mb_decision = 2; - pCtx->last_predictor_count = 3; - pCtx->pre_dia_size = 2; - pCtx->dia_size = 2; - pCtx->max_b_frames = 2; - pCtx->b_frame_strategy = 2; - pCtx->trellis = 2; - pCtx->compression_level = 2; - pCtx->global_quality = 300; - pCtx->pre_me = 2; - pCtx->mv0_threshold = 1; - // pCtx->quantizer_noise_shaping = 2; // deprecated - // TODO - } - - pCtx->time_base = (AVRational){1, 25}; /////TODO FIX TO SUPPORT OTHER RATES - // pCtx->time_base = (AVRational){1, 10}; - pCtx->gop_size = 12; // emit one intra frame every twelve frames - // pCtx->max_b_frames = 0; - pCtx->pix_fmt = PIX_FMT_YUV420P; - if (fmt->flags & AVFMT_GLOBALHEADER) - pCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; - - if (pCtx->codec_id == CODEC_ID_H264) - { - // http://stackoverflow.com/questions/3553003/encoding-h-264-with-libavcodec-x264 - pCtx->coder_type = 1; // coder = 1 - pCtx->flags|=CODEC_FLAG_LOOP_FILTER; // flags=+loop - pCtx->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1 - // pCtx->partitions|=X264_PART_I8X8+X264_PART_I4X4+X264_PART_P8X8+X264_PART_B8X8; // partitions=+parti8x8+parti4x4+partp8x8+partb8x8 - pCtx->me_method=ME_HEX; // me_method=hex - pCtx->me_subpel_quality = 7; // subq=7 - pCtx->me_range = 16; // me_range=16 - pCtx->gop_size = 250; // g=250 - pCtx->keyint_min = 25; // keyint_min=25 - pCtx->scenechange_threshold = 40; // sc_threshold=40 - pCtx->i_quant_factor = 0.71; // i_qfactor=0.71 - pCtx->b_frame_strategy = 1; // b_strategy=1 - pCtx->qcompress = 0.6; // qcomp=0.6 - pCtx->qmin = 10; // qmin=10 - pCtx->qmax = 51; // qmax=51 - pCtx->max_qdiff = 4; // qdiff=4 - pCtx->max_b_frames = 3; // bf=3 - pCtx->refs = 3; // refs=3 - // pCtx->directpred = 1; // directpred=1 - pCtx->trellis = 1; // trellis=1 - // pCtx->flags2|=CODEC_FLAG2_BPYRAMID+CODEC_FLAG2_MIXED_REFS+CODEC_FLAG2_WPRED+CODEC_FLAG2_8X8DCT+CODEC_FLAG2_FASTPSKIP; // flags2=+bpyramid+mixed_refs+wpred+dct8x8+fastpskip - // pCtx->weighted_p_pred = 2; // wpredp=2 - // libx264-main.ffpreset preset - // pCtx->flags2|=CODEC_FLAG2_8X8DCT; - // pCtx->flags2^=CODEC_FLAG2_8X8DCT; // flags2=-dct8x8 - } - - AVCodec * codec = avcodec_find_encoder(pCtx->codec_id); - if (NULL == codec) - throw std::runtime_error("Unable to find Mpeg4 codec"); - if (codec->pix_fmts) - pCtx->pix_fmt = codec->pix_fmts[0]; - { - //QMutexLocker lock(&decoder::mutex); - if (avcodec_open2(pCtx, codec, NULL) < 0) - throw std::runtime_error("Error opening codec"); - } - - /* Get framebuffers */ - if (! (picture_yuv = avcodec_alloc_frame()) ) // final frame format - throw std::runtime_error(""); - if (! (picture_rgb = avcodec_alloc_frame()) ) // rgb version I can understand easily - throw std::runtime_error(""); - /* the image can be allocated by any means and av_image_alloc() is - * just the most convenient way if av_malloc() is to be used */ - if ( av_image_alloc(picture_yuv->data, picture_yuv->linesize, - pCtx->width, pCtx->height, pCtx->pix_fmt, 1) < 0 ) - throw std::runtime_error("Error allocating YUV frame buffer"); - if ( av_image_alloc(picture_rgb->data, picture_rgb->linesize, - pCtx->width, pCtx->height, PIX_FMT_RGB24, 1) < 0 ) - throw std::runtime_error("Error allocating RGB frame buffer"); - - /* Init scale & convert */ - if (! (Sctx=sws_getContext( - width, - height, - PIX_FMT_RGB24, - pCtx->width, - pCtx->height, - pCtx->pix_fmt, - SWS_BICUBIC,NULL,NULL,NULL)) ) - throw std::runtime_error(""); - -// -// -// added audio init - AVCodec * acodec = avcodec_find_encoder(AV_CODEC_ID_AAC); - int ret = avcodec_open2(pCtx, acodec, NULL); - if (ret < 0) { - throw std::runtime_error("Could not open audio codec:"); - - } - - if (pCtx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) - audio_input_frame_size = 10000; - else - audio_input_frame_size = pCtx->frame_size; //is coming out at 0? - - audiostep=((float)audio_input_frame_size)/(pCtx->sample_rate); - - -// are we supposed to use the same codeccontext? -// - - /* open the output file */ - if (!(fmt->flags & AVFMT_NOFILE)) - { - //QMutexLocker lock(&decoder::mutex); - if (avio_open(&container->pb, file_name, AVIO_FLAG_WRITE) < 0) - throw std::runtime_error("Error opening output video file"); - } - avformat_write_header(container, NULL); -} - -void libav::encoder::setPixelIntensity(int x, int y, int c, uint8_t value) -{ - uint8_t * ptr = picture_rgb->data[0] + y * picture_rgb->linesize[0] + x * 3 + c; - *ptr = value; -} - -void libav::encoder::write_frame(float seconds,uint8_t *rgbdata) -{ - picture_rgb->data[0]=rgbdata; - - // convert from RGB24 to YUV - sws_scale(Sctx, // sws context - picture_rgb->data, // src slice - picture_rgb->linesize, // src stride - 0, // src slice origin y - pCtx->height, // src slice height - picture_yuv->data, // dst - picture_yuv->linesize ); // dst stride - - /* encode the image */ - // use non-deprecated avcodec_encode_video2(...) - AVPacket packet; - av_init_packet(&packet); - packet.data = NULL; - packet.size = 0; - - //no time stamps as is - //http://dranger.com/ffmpeg/tutorial07.html - - picture_yuv->pts=(uint64_t)(seconds*timebase); - - int got_packet; - int ret = avcodec_encode_video2(pCtx, - &packet, - picture_yuv, - &got_packet); - if (ret < 0) - throw std::runtime_error("Video encoding failed"); - if (got_packet) - { - // std::cout << "encoding frame" << std::endl; - int result = av_write_frame(container, &packet); - av_destruct_packet(&packet); - } -} -void libav::encoder::write_frame(float seconds,uint16_t *audiodata){ - audio_frame = avcodec_alloc_frame(); - AVPacket pkt = { 0 }; // data and size must be 0; - int got_packet, ret; - av_init_packet(&pkt); - audio_frame->nb_samples = audio_input_frame_size; - uint8_t *sampleptr; - int bufsize=audio_input_frame_size * av_get_bytes_per_sample(pCtx->sample_fmt) *pCtx->channels; - if (audiodata) { - sampleptr=(uint8_t*)audiodata; - } - else { - sampleptr=new uint8_t[bufsize]; - memset(sampleptr,0,bufsize); - } - - avcodec_fill_audio_frame(audio_frame, pCtx->channels, pCtx->sample_fmt, - sampleptr, - audio_input_frame_size * - av_get_bytes_per_sample(pCtx->sample_fmt) * - pCtx->channels, 0); //; - - audio_frame->pts=(uint64_t)(seconds*timebase); - - ret = avcodec_encode_audio2(pCtx, &pkt, audio_frame, &got_packet); - if (!audiodata) { - delete[] sampleptr; - } - if (ret < 0) { - throw std::runtime_error("Audio encoding failed"); - } - - if (!got_packet) - return; - - // ? pkt.stream_index = st->index; - - ret = av_interleaved_write_frame(container, &pkt); - avcodec_free_frame(&audio_frame); -} - -/* virtual */ -libav::encoder::~encoder() -{ - int result = av_write_frame(container, NULL); // flush - result = av_write_trailer(container); - { - //QMutexLocker lock(&decoder::mutex); - avio_close(container->pb); - } - for (int i = 0; i < container->nb_streams; ++i) - av_freep(container->streams[i]); - av_free(container); - container = NULL; - - { - //QMutexLocker lock(&decoder::mutex); - avcodec_close(pCtx); - } - av_free(pCtx); - pCtx = NULL; - av_free(picture_yuv->data[0]); - av_free(picture_yuv); - picture_yuv = NULL; - av_free(picture_rgb->data[0]); - av_free(picture_rgb); - picture_rgb = NULL; -} - -bool libav::exporter::setup(int w,int h, int bitRate, int frameRate, std::string container){ - - maybeInitFFMpegLib(); - - this->w=w; - this->h=h; - this->bitRate=bitRate; - this->frameRate=frameRate; - this->container=container; - - return true; -} - -bool libav::exporter::record(std::string filename){ - - // allocate the output media context // - avformat_alloc_output_context2(&oc, NULL, NULL, filename.c_str()); - if (!oc) { - printf("Could not deduce output format from file extension: using MPEG.\n"); - avformat_alloc_output_context2(&oc, NULL, "mpeg", filename.c_str()); - } - if (!oc) { - return false; - } - fmt = oc->oformat; - - // Add the audio and video streams using the default format codecs - // * and initialize the codecs. // - video_st = NULL; - audio_st = NULL; - - if (fmt->video_codec != AV_CODEC_ID_NONE) { - video_st = add_stream(oc, &video_codec, fmt->video_codec); - } - if (fmt->audio_codec != AV_CODEC_ID_NONE) { - audio_st = add_stream(oc, &audio_codec, fmt->audio_codec); - } - - //set initial video params - video_st->codec->width=w; - video_st->codec->height=h; - video_st->codec->time_base.num = 1;//codecCtx->ticks_per_frame; - video_st->codec->time_base.den = frameRate; - video_st->time_base = video_st->codec->time_base; - //audioStream->time_base = codecCtx->time_base; //???has the capability of crashing - - video_st->codec->gop_size = 10; /* emit one intra frame every ten frames */ - video_st->codec->pix_fmt = PIX_FMT_YUV420P; - - // Now that all the parameters are set, we can open the audio and - // * video codecs and allocate the necessary encode buffers. // - if (video_st) - open_video(oc, video_codec, video_st); - if (audio_st) { - audioframesize=open_audio(oc, audio_codec, audio_st); - audiostep=((float)audioframesize)/(audio_st->codec->sample_rate); - std::cerr << "opened audio codec with "<flags & AVFMT_NOFILE)) { - int ret = avio_open(&oc->pb, filename.c_str(), AVIO_FLAG_WRITE); - if (ret < 0) { - std::cerr <<"Could not open " << filename.c_str() << std::endl; - return false; - } - } - - // Write the stream header, if any. // - int ret = avformat_write_header(oc, NULL); - if (ret < 0) { - //std::cerr <<"Error occurred when opening output file:" << av_err2str(ret) << std::endl; - return false; - } - - if (frame) - frame->pts = 0; - - outputframe=0; - - return true; -} -bool libav::exporter::encodeFrame(unsigned char *pixels,uint16_t *samples){ - // Compute current audio and video time. // - if (audio_st) - audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; - else - audio_pts = 0.0; - - if (video_st) - video_pts = (double)video_st->pts.val * video_st->time_base.num / - video_st->time_base.den; - else - video_pts = 0.0; - - // write interleaved audio and video frames // - if (!video_st || (video_st && audio_st && audio_pts < video_pts)) { - write_audio_frame(oc, audio_st, samples); - } else { - write_video_frame(oc, video_st, pixels); - - frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base); - } - - //std::cerr << "encoded frame " << outputframe << std::endl; - outputframe++; - - return true; -} -bool libav::exporter::encodeFrame(unsigned char *pixels,AVPacket *audio){ - // Compute current audio and video time. // - if (audio_st) - audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; - else - audio_pts = 0.0; - - if (video_st) - video_pts = (double)video_st->pts.val * video_st->time_base.num / - video_st->time_base.den; - else - video_pts = 0.0; - - // write interleaved audio and video frames // - if (!video_st || (video_st && audio_st && audio_pts < video_pts)) { - write_audio_frame(oc, audio_st, audio); - } else { - write_video_frame(oc, video_st, pixels); - - frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base); - } - - //std::cerr << "encoded frame " << outputframe << std::endl; - outputframe++; - - return true; -} -bool libav::exporter::encodeFrame(unsigned char *pixels){ - video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; - write_video_frame(oc, video_st, pixels); - frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base); - outputframe++; - return true; -} -bool libav::exporter::encodeFrame(uint16_t *samples){ - audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; - write_audio_frame(oc, audio_st, samples); - return true; -} -void libav::exporter::finishRecord(){ - - av_write_trailer(oc); - // Close each codec. // - if (video_st) - close_video(oc, video_st); - if (audio_st) - close_audio(oc, audio_st); - - if (!(fmt->flags & AVFMT_NOFILE)) - // Close the output file. // - avio_close(oc->pb); - - // free the stream // - avformat_free_context(oc); -} - -AVStream* libav::exporter::add_stream(AVFormatContext *oc, AVCodec **codec,enum AVCodecID codec_id) - { - AVCodecContext *c; - AVStream *st; - - // find the encoder // - *codec = avcodec_find_encoder(codec_id); - if (!(*codec)) { - //fprintf(stderr, "Could not find encoder for '%s'\n", - // avcodec_get_name(codec_id)); - exit(1); - } - - st = avformat_new_stream(oc, *codec); - if (!st) { - //fprintf(stderr, "Could not allocate stream\n"); - exit(1); - } - st->id = oc->nb_streams-1; - c = st->codec; - - switch ((*codec)->type) { - case AVMEDIA_TYPE_AUDIO: - st->id = 1; - c->sample_fmt = AV_SAMPLE_FMT_S16; - c->bit_rate = 64000; - c->sample_rate = 44100; - c->channels = 2; - c->channel_layout=AV_CH_LAYOUT_STEREO; - break; - - case AVMEDIA_TYPE_VIDEO: - c->codec_id = codec_id; - - c->bit_rate = 400000; - // Resolution must be a multiple of two. // - c->width = 352; - c->height = 288; - // timebase: This is the fundamental unit of time (in seconds) in terms - // * of which frame timestamps are represented. For fixed-fps content, - // * timebase should be 1/framerate and timestamp increments should be - // * identical to 1. // - c->time_base.den = frameRate; - c->time_base.num = 1; - c->gop_size = 12; // emit one intra frame every twelve frames at most // - c->pix_fmt = AV_PIX_FMT_YUV420P; //ADDED HARDCODED TJR 280513 - if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - // just for testing, we also add B frames // - c->max_b_frames = 2; - } - if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) { - // Needed to avoid using macroblocks in which some coeffs overflow. - // * This does not happen with normal video, it just happens here as - // * the motion of the chroma plane does not match the luma plane. // - c->mb_decision = 2; - } - break; - - default: - break; - } - - // Some formats want stream headers to be separate. // - if (oc->oformat->flags & AVFMT_GLOBALHEADER) - c->flags |= CODEC_FLAG_GLOBAL_HEADER; - - return st; - } - -void libav::exporter::open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st) - { - int ret; - AVCodecContext *c = st->codec; - - // open the codec // - ret = avcodec_open2(c, codec, NULL); - if (ret < 0) { - //fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret)); - exit(1); - } - - // allocate and init a re-usable frame // - frame = avcodec_alloc_frame(); - if (!frame) { - //fprintf(stderr, "Could not allocate video frame\n"); - exit(1); - } - - // Allocate the encoded raw picture. // - ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height); - if (ret < 0) { - //fprintf(stderr, "Could not allocate picture: %s\n", av_err2str(ret)); - exit(1); - } - - // If the output format is not YUV420P, then a temporary YUV420P - // * picture is needed too. It is then converted to the required - // * output format. // - if (c->pix_fmt != AV_PIX_FMT_YUV420P) { - ret = avpicture_alloc(&src_picture, AV_PIX_FMT_RGB24, c->width, c->height); - if (ret < 0) { - //fprintf(stderr, "Could not allocate temporary picture: %s\n", - // av_err2str(ret)); - exit(1); - } - } - - // copy data and linesize picture pointers to frame // - *((AVPicture *)frame) = dst_picture; - - outPixels = (uint8_t*)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, st->codec->width,st->codec->height)); - } - - int libav::exporter::open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st) - { - AVCodecContext *c; - int ret; - - c = st->codec; - - // open it // - ret = avcodec_open2(c, codec, NULL); - if (ret < 0) { - //fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret)); - exit(1); - } - - // init signal generator // - t = 0; - tincr = 2 * M_PI * 110.0 / c->sample_rate; - // increment frequency by 110 Hz per second // - tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; - - if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) - audio_input_frame_size = 10000; - else - audio_input_frame_size = c->frame_size; - - /* - samples = av_malloc(audio_input_frame_size * - av_get_bytes_per_sample(c->sample_fmt) * - c->channels); - if (!samples) { - //fprintf(stderr, "Could not allocate audio samples buffer\n"); - exit(1); - } - */ - return audio_input_frame_size; - } - - void libav::exporter::write_audio_frame(AVFormatContext *oc, AVStream *st,uint16_t *samples) - { - AVCodecContext *c; - AVPacket pkt = { 0 }; // data and size must be 0; - AVFrame *frame = avcodec_alloc_frame(); - int got_packet, ret; - - av_init_packet(&pkt); - c = st->codec; - - //get_audio_frame(samples, audio_input_frame_size, c->channels); - frame->nb_samples = audio_input_frame_size; - uint8_t *sampleptr; - int bufsize=audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt) *c->channels; - if (samples) { - sampleptr=(uint8_t*)samples; - } - else { - sampleptr=new uint8_t[bufsize]; - memset(sampleptr,0,bufsize); - } - - avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, - sampleptr, - audio_input_frame_size * - av_get_bytes_per_sample(c->sample_fmt) * - c->channels, 0); //; - //frame->sample_rate=44100; //hard coded input rate- nope, this doesn't help - //frame->format=AV_SAMPLE_FMT_S16P; - //?? why is ffmpeg reporting fltp as the sample format??? doesn't seem to have an effect to change this though - ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet); - if (!samples) { - delete[] sampleptr; - } - if (ret < 0) { - //fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); - exit(1); - } - - if (!got_packet) - return; - - pkt.stream_index = st->index; - - // Write the compressed frame to the media file. // - ret = av_interleaved_write_frame(oc, &pkt); - if (ret != 0) { - //fprintf(stderr, "Error while writing audio frame: %s\n", - // av_err2str(ret)); - exit(1); - } - avcodec_free_frame(&frame); - } - - void libav::exporter::write_audio_frame(AVFormatContext *oc, AVStream *st,AVPacket *pkt) - { - /* - AVCodecContext *c; - AVPacket pkt = { 0 }; // data and size must be 0; - AVFrame *frame = avcodec_alloc_frame(); - int got_packet, ret; - - av_init_packet(&pkt); - c = st->codec; - - //get_audio_frame(samples, audio_input_frame_size, c->channels); - frame->nb_samples = audio_input_frame_size; - uint8_t *sampleptr; - int bufsize=audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt) *c->channels; - if (samples) { - sampleptr=(uint8_t*)samples; - } - else { - sampleptr=new uint8_t[bufsize]; - memset(sampleptr,0,bufsize); - } - avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, - sampleptr, - audio_input_frame_size * - av_get_bytes_per_sample(c->sample_fmt) * - c->channels, 1); - - ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet); - if (!samples) { - free(sampleptr); - } - if (ret < 0) { - //fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); - exit(1); - } - - if (!got_packet) - return; - */ - - pkt->stream_index = st->index; - - // Write the compressed frame to the media file. // - int ret = av_interleaved_write_frame(oc, pkt); - if (ret != 0) { - //fprintf(stderr, "Error while writing audio frame: %s\n", - // av_err2str(ret)); - exit(1); - } - //avcodec_free_frame(&frame); - av_free_packet(pkt); - } - - void libav::exporter::close_audio(AVFormatContext *oc, AVStream *st) - { - avcodec_close(st->codec); - - - } - - void libav::exporter::write_video_frame(AVFormatContext *oc, AVStream *st, uint8_t *pixels) - { - int ret; - static struct SwsContext *sws_ctx; - AVCodecContext *c = st->codec; - -/* - if (frame_count >= STREAM_NB_FRAMES) { - // No more frames to compress. The codec has a latency of a few - // * frames if using B-frames, so we get the last frames by - // * passing the same picture again. // - } else { - if (c->pix_fmt != AV_PIX_FMT_YUV420P) { - // as we only generate a YUV420P picture, we must convert it - // * to the codec pixel format if needed // - if (!sws_ctx) { - sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_YUV420P, - c->width, c->height, c->pix_fmt, - sws_flags, NULL, NULL, NULL); - if (!sws_ctx) { - //fprintf(stderr, - // "Could not initialize the conversion context\n"); - exit(1); - } - } - fill_yuv_image(&src_picture, frame_count, c->width, c->height); - sws_scale(sws_ctx, - (const uint8_t * const *)src_picture.data, src_picture.linesize, - 0, c->height, dst_picture.data, dst_picture.linesize); - } else { - fill_yuv_image(&dst_picture, frame_count, c->width, c->height); - } - } -*/ - //always convert RGB to YUV - //should be context allocated once per render instead of per frame?? - // - // - sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_RGB24, - c->width, c->height, AV_PIX_FMT_YUV420P, - sws_flags, NULL, NULL, NULL); - - avpicture_fill(&src_picture, pixels, PIX_FMT_RGB24, c->width,c->height); - //avpicture_fill(&dst_picture, outPixels, PIX_FMT_YUV420P, c->width,c->height); - - sws_scale(sws_ctx, src_picture.data, src_picture.linesize, 0, c->height, dst_picture.data, dst_picture.linesize); - //fill_yuv_image(&dst_picture, frame_count, c->width, c->height); - if (oc->oformat->flags & AVFMT_RAWPICTURE) { - // Raw video case - directly store the picture in the packet // - AVPacket pkt; - av_init_packet(&pkt); - - pkt.flags |= AV_PKT_FLAG_KEY; - pkt.stream_index = st->index; - pkt.data = dst_picture.data[0]; - pkt.size = sizeof(AVPicture); - - ret = av_interleaved_write_frame(oc, &pkt); - } else { - AVPacket pkt = { 0 }; - int got_packet; - av_init_packet(&pkt); - - // encode the image // - ret = avcodec_encode_video2(c, &pkt, frame, &got_packet); - if (ret < 0) { - //fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret)); - exit(1); - } - // If size is zero, it means the image was buffered. // - - if (!ret && got_packet && pkt.size) { - pkt.stream_index = st->index; - - // Write the compressed frame to the media file. // - ret = av_interleaved_write_frame(oc, &pkt); - } else { - ret = 0; - } - } - - // - // added 22 may in memory leak run - // - sws_freeContext(sws_ctx); //should be done once per render instead of per frame?? - - if (ret != 0) { - //fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret)); - exit(1); - } - frame_count++; - - //avcodec_free_frame(&frame); - } - - void libav::exporter::close_video(AVFormatContext *oc, AVStream *st) - { - avcodec_close(st->codec); - av_free(src_picture.data[0]); - av_free(dst_picture.data[0]); - av_free(frame); - av_free(outPixels); //SIGSEV here??? - } - -bool libav::audioloader::setup(const std::string &filename){ - - maybeInitFFMpegLib(); - - frame = avcodec_alloc_frame(); - if (!frame) - { - std::cout << "Error allocating the frame" << std::endl; - return false; - } - - formatContext = NULL; - if (avformat_open_input(&formatContext, filename.c_str(), NULL, NULL) != 0) - { - av_free(frame); - std::cout << "Error opening the file" << std::endl; - return false; - } - - if (avformat_find_stream_info(formatContext, NULL) < 0) - { - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Error finding the stream info" << std::endl; - return false; - } - - audioStream = NULL; - for (unsigned int i = 0; i < formatContext->nb_streams; ++i) - { - if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) - { - audioStream = formatContext->streams[i]; - break; - } - } - - if (audioStream == NULL) - { - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Could not find any audio stream in the file" << std::endl; - return false; - } - - codecContext = audioStream->codec; - - codecContext->codec = avcodec_find_decoder(codecContext->codec_id); - if (codecContext->codec == NULL) - { - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Couldn't find a proper decoder" << std::endl; - return false; - } - else if (avcodec_open2(codecContext, codecContext->codec, NULL) != 0) - { - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Couldn't open the context with the decoder" << std::endl; - return false; - } - - av_dump_format(formatContext, 0, 0, false); //avformat.h line 1256 - int samples = ((formatContext->duration + 5000)*codecContext->sample_rate)/AV_TIME_BASE; - - std::cout << "This stream has " << codecContext->channels << " channels, a sample rate of " << codecContext->sample_rate << "Hz and "<sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ") "<index) - { - //int bytes = - avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); - - // Some frames rely on multiple packets, so we have to make sure the frame is finished before - // we can use it - } - // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory - av_free_packet(&packet); - } - return frame; - - } - AVPacket* libav::audioloader::get_packet() { - - if (!ready) return nullptr; - - int ret=av_read_frame(formatContext, &packet); - if (ret<0) { - std::cerr << "finished with code "<index) - //{ - //int bytes = - // avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); - - // Some frames rely on multiple packets, so we have to make sure the frame is finished before - // we can use it - //} - // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory - //av_free_packet(&packet);????? - //} - return &packet; - - } - uint16_t* libav::audioloader::get_samples(int num){ //presumes 16bpc here - //std::cerr << "request "<0){ - for (int i=0;inb_samples))*channels)>buffer.size()){ - int m=buffer.size(); - int s=((sample_end+std::max(num,frame->nb_samples))*channels); - buffer.reserve(s); - std::cerr << "audioloader reserved buffer to " << s << std::endl; - for (int i=m;inb_samples;i++) { - for (int j=0;jformat - //format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames, enum AVSampleFormat for audio) - int ff=frame->format; - //uint64_t frame->channel_layout - //Channel layout of the audio data. - uint64_t fcl=frame->channel_layout; - //int frame->nb_extended_buf - //Number of elements in extended_buf. - int fnb=frame->nb_extended_buf; - //int frame->decode_error_flags - //decode error flags of the frame, set to a combination of FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there were errors during the decoding. - int fde=frame->decode_error_flags; - - - //uint16_t s=((uint16_t*) frame->buf[j]->data)[i]; - uint16_t s=((uint16_t*) frame->buf[0]->data)[j*channels+i]; - //which? must be determined by format or layout of the channels - //ALSO some kind of HEINOUS memory leak?? - buffer[((sample_end+i)*frame->channels)+j]=s; - //buffer[(j*frame->channels)+(sample_end+i)]= ((uint16_t*) frame->buf[j]->data)[i]; ??planar?? nope - } - } - sample_end+=frame->nb_samples; - } - else { - for (int i=sample_end;inb_samples)*frame->channels)<num) { - sample_start=num; - } - else { - sample_start=0; - } - return (uint16_t*)(&buffer[0]); -} - -bool libav::audioloader::close() { - av_free(frame); - avcodec_close(codecContext); - avformat_close_input(&formatContext); - - return true; -} \ No newline at end of file diff --git a/rotord/libav/libavwrapper.h b/rotord/libav/libavwrapper.h deleted file mode 100755 index a8b0f23..0000000 --- a/rotord/libav/libavwrapper.h +++ /dev/null @@ -1,248 +0,0 @@ - #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 - */ - - -#ifndef UINT64_C -#define UINT64_C(c) (c ## ULL) -#endif - - - -extern "C" { -#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 - //static QMutex mutex; - 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); - 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_MPEG4); - 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; - - 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; - - 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; - private: - std::vector buffer; - AVFrame* frame; - - AVStream* audioStream; - - AVPacket packet; - int sample_end; - int sample_start; - int channels; //necessary to handle final packet - }; - -} - - - -#endif // libavwrapper_H diff --git a/rotord/libavaudioloader.cpp b/rotord/libavaudioloader.cpp deleted file mode 100644 index a634740..0000000 --- a/rotord/libavaudioloader.cpp +++ /dev/null @@ -1,231 +0,0 @@ -#include "libavaudioloader.h" - -bool libav::Audioloader::setup(const std::string &filename){ - - av_register_all(); - - frame = avcodec_alloc_frame(); - if (!frame) - { - std::cout << "Error allocating the frame" << std::endl; - return false; - } - - formatContext = NULL; - if (avformat_open_input(&formatContext, filename.c_str(), NULL, NULL) != 0) - { - av_free(frame); - std::cout << "Error opening the file" << std::endl; - return false; - } - - if (avformat_find_stream_info(formatContext, NULL) < 0) - { - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Error finding the stream info" << std::endl; - return false; - } - - audioStream = NULL; - for (unsigned int i = 0; i < formatContext->nb_streams; ++i) - { - if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) - { - audioStream = formatContext->streams[i]; - break; - } - } - - if (audioStream == NULL) - { - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Could not find any audio stream in the file" << std::endl; - return false; - } - - codecContext = audioStream->codec; - - codecContext->codec = avcodec_find_decoder(codecContext->codec_id); - if (codecContext->codec == NULL) - { - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Couldn't find a proper decoder" << std::endl; - return false; - } - else if (avcodec_open2(codecContext, codecContext->codec, NULL) != 0) - { - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Couldn't open the context with the decoder" << std::endl; - return false; - } - - av_dump_format(formatContext, 0, 0, false); //avformat.h line 1256 - int samples = ((formatContext->duration + 5000)*codecContext->sample_rate)/AV_TIME_BASE; - - std::cout << "This stream has " << codecContext->channels << " channels, a sample rate of " << codecContext->sample_rate << "Hz and "<sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ") "<index) - { - //int bytes = - avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); - - // Some frames rely on multiple packets, so we have to make sure the frame is finished before - // we can use it - } - // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory - av_free_packet(&packet); - } - return frame; - - } - AVPacket* libav::Audioloader::get_packet() { - - if (!ready) return nullptr; - - int ret=av_read_frame(formatContext, &packet); - if (ret<0) { - std::cerr << "finished with code "<index) - //{ - //int bytes = - // avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); - - // Some frames rely on multiple packets, so we have to make sure the frame is finished before - // we can use it - //} - // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory - //av_free_packet(&packet);????? - //} - return &packet; - - } - -/* - // Some codecs will cause frames to be buffered up in the decoding process. If the CODEC_CAP_DELAY flag - // is set, there can be buffered up frames that need to be flushed, so we'll do that - if (codecContext->codec->capabilities & CODEC_CAP_DELAY) - { - av_init_packet(&packet); - // Decode all the remaining frames in the buffer, until the end is reached - int frameFinished = 0; - int bytes = avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); - while (bytes >= 0 && frameFinished) - { - for (auto p: processors) { - p->process_frame(frame->data[0],frame->nb_samples); - } - mutex.lock(); - progress=((double)sample_processed)/samples; - mutex.unlock(); - } - } - - cerr << "finished processing: "<0){ - for (int i=0;inb_samples))*channels)>buffer.size()){ - int m=buffer.size(); - int s=((sample_end+std::max(num,frame->nb_samples))*channels); - buffer.reserve(s); - std::cerr << "audioloader reserved buffer to " << s << std::endl; - for (int i=m;inb_samples;i++) { - for (int j=0;jformat - //format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames, enum AVSampleFormat for audio) - int ff=frame->format; - //uint64_t frame->channel_layout - //Channel layout of the audio data. - uint64_t fcl=frame->channel_layout; - //int frame->nb_extended_buf - //Number of elements in extended_buf. - int fnb=frame->nb_extended_buf; - //int frame->decode_error_flags - //decode error flags of the frame, set to a combination of FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there were errors during the decoding. - int fde=frame->decode_error_flags; - - - //uint16_t s=((uint16_t*) frame->buf[j]->data)[i]; - uint16_t s=((uint16_t*) frame->buf[0]->data)[j*channels+i]; - //which? must be determined by format or layout of the channels - //ALSO some kind of HEINOUS memory leak?? - buffer[((sample_end+i)*frame->channels)+j]=s; - //buffer[(j*frame->channels)+(sample_end+i)]= ((uint16_t*) frame->buf[j]->data)[i]; ??planar?? nope - } - } - sample_end+=frame->nb_samples; - } - else { - for (int i=sample_end;inb_samples)*frame->channels)<num) { - sample_start=num; - } - else { - sample_start=0; - } - return (uint16_t*)(&buffer[0]); -} - -bool libav::Audioloader::close() { - av_free(frame); - avcodec_close(codecContext); - avformat_close_input(&formatContext); - - return true; -} diff --git a/rotord/libavaudioloader.h b/rotord/libavaudioloader.h deleted file mode 100644 index 8c4ddf1..0000000 --- a/rotord/libavaudioloader.h +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include -#include -#include -#include - -extern "C" { - #include - #include - #include -} - -namespace libav { - - 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; - private: - std::vector buffer; - AVFrame* frame; - - AVStream* audioStream; - - AVPacket packet; - int sample_end; - int sample_start; - int channels; //necessary to handle final packet - }; - - -} diff --git a/rotord/libavwrapper_guarded.cpp b/rotord/libavwrapper_guarded.cpp deleted file mode 100755 index be61ae9..0000000 --- a/rotord/libavwrapper_guarded.cpp +++ /dev/null @@ -1,1694 +0,0 @@ -#include "libavwrapper_guarded.h" - -extern Poco::Mutex mutex; //application wide mutex -static Poco::Mutex mutex; - -///this seems to create a long pause and finally crash - -extern "C" -{ -#include -} - -/* -#include -#include -#include -#include -#include -#include -*/ - -#include -#include -#include - -using namespace std; - -// Translated to C++ by Christopher Bruns May 2012 -// from ffmeg_adapt.c in whisk package by Nathan Clack, Mark Bolstadt, Michael Meeuwisse - -//QMutex decoder::mutex; - -// Avoid link error on some macs -#ifdef __APPLE__ -extern "C" { -#include -#include -// #include "compiler/compiler.h" - -/* - * Darwin doesn't have posix_memalign(), provide a private - * weak alternative - */ - /* -int __weak posix_memalign(void **ptr, size_t align, size_t size) -{ - if (*ptr) - return 0; - - return ENOMEM; -} -*/ -} -#endif - -// Custom read function so FFMPEG does not need to read from a local file by name. -// But rather from a stream derived from a URL or whatever. -extern "C" { - -int readFunction(void* opaque, uint8_t* buf, int buf_size) -{ - //QIODevice* stream = (QIODevice*)opaque; - ifstream* stream = (ifstream*)opaque; - //int numBytes = - stream->read((char*)buf, (streamsize)buf_size); - return stream->gcount(); //?? is this right - //numBytes; //TODO work out -} - -// http://cdry.wordpress.com/2009/09/09/using-custom-io-callbacks-with-ffmpeg/ -int64_t seekFunction(void* opaque, int64_t offset, int whence) -{ - //QIODevice* stream = (QIODevice*)opaque; - ifstream* stream = (ifstream*)opaque; - if (stream == NULL) - return -1; - else if (whence == AVSEEK_SIZE) - return -1; // "size of my handle in bytes" - //else if (stream->isSequential()) - // return -1; // cannot seek a sequential stream //presume this would be certain kind of network stream - else if (whence == SEEK_CUR) { // relative to start of file - if (! stream->seekg(offset,ios_base::cur)) //stream->pos() + offset) ) - return -1; - } - else if (whence == SEEK_END) { // relative to end of file - assert(offset < 0); - if (! stream->seekg(offset,ios_base::end)) //stream->size() + offset) ) - return -1; - } - else if (whence == SEEK_SET) { // relative to start of file - if (! stream->seekg(offset) ) - return -1; - } - else { - assert(false); - } - return stream->tellg(); -} - -} - - -///////////////////////////// -// AVPacketWrapper methods // -///////////////////////////// - - -class AVPacketWrapper -{ -public: - AVPacketWrapper(); - virtual ~AVPacketWrapper(); - void free(); - - AVPacket packet; -}; - - -AVPacketWrapper::AVPacketWrapper() -{ - packet.destruct = NULL; -} - -/* virtual */ -AVPacketWrapper::~AVPacketWrapper() -{ - free(); -} - -void AVPacketWrapper::free() -{ - av_free_packet(&packet); -} - - -//bool libav::b_is_one_time_inited = false; - -///////////////////////// -// decoder methods // -///////////////////////// - -libav::decoder::decoder(PixelFormat pixelFormat) - : isOpen(false) -{ - mutex.lock(); - initialize(); - format = pixelFormat; - mutex.unlock(); -} - -/* -decoder::decoder(QUrl url, PixelFormat pixelFormat) - : isOpen(false) -{ - //QMutexLocker lock(&decoder::mutex); - initialize(); - format = pixelFormat; - isOpen = open(url, pixelFormat); -} -*/ - -void libav::decoder::cleanup(){ - //QMutexLocker lock(&decoder::mutex); - mutex.lock(); - if (NULL != Sctx) { - sws_freeContext(Sctx); - Sctx = NULL; - } - if (NULL != pRaw) { - av_free(pRaw); - pRaw = NULL; - } - if (NULL != pFrameRGB) { - av_free(pFrameRGB); - pFrameRGB = NULL; - } - if (NULL != pCtx) { - avcodec_close(pCtx); - pCtx = NULL; - } - if (NULL != container) { - avformat_close_input(&container); - container = NULL; - } - if (NULL != buffer) { - av_free(buffer); - buffer = NULL; - } - if (NULL != blank) { - av_free(blank); - blank = NULL; - } - mutex.unlock(); - /* - if (NULL != avioContext) { - av_free(avioContext); - avioContext = NULL; - } - */ - //QNetworkreply - //if (reply != NULL) { - // reply->deleteLater(); - // reply = NULL; - //} - // Don't need to free pCodec? - -} - -/* virtual */ -libav::decoder::~decoder() -{ - cleanup(); -} -/* -bool decoder::open(QUrl url, enum PixelFormat formatParam) -{ - if (url.isEmpty()) - return false; - - // Is the movie source a local file? - if (url.host() == "localhost") - url.setHost(""); - QString fileName = url.toLocalFile(); - if ( (! fileName.isEmpty()) - && (QFileInfo(fileName).exists()) ) - { - // return open(fileName, formatParam); // for testing only - - // Yes, the source is a local file - fileStream.setFileName(fileName); - // qDebug() << fileName; - if (! fileStream.open(QIODevice::ReadOnly)) - return false; - return open(fileStream, fileName, formatParam); - } - - // ...No, the source is not a local file - if (url.host() == "") - url.setHost("localhost"); - fileName = url.path(); - - // http://stackoverflow.com/questions/9604633/reading-a-file-located-in-memory-with-libavformat - // Load from URL - QEventLoop loop; // for synchronous url fetch http://stackoverflow.com/questions/5486090/qnetworkreply-wait-for-finished - QObject::connect(&networkManager, SIGNAL(finished(QNetworkReply*)), - &loop, SLOT(quit())); - QNetworkRequest request = QNetworkRequest(url); - // qDebug() << "networkManager" << __FILE__ << __LINE__; - reply = networkManager.get(request); - loop.exec(); - if (reply->error() != QNetworkReply::NoError) { - // qDebug() << reply->error(); - reply->deleteLater(); - reply = NULL; - return false; - } - QIODevice * stream = reply; - // Mpeg needs seekable device, so create in-memory buffer if necessary - if (stream->isSequential()) { - byteArray = stream->readAll(); - fileBuffer.setBuffer(&byteArray); - fileBuffer.open(QIODevice::ReadOnly); - if (! fileBuffer.seek(0)) - return false; - stream = &fileBuffer; - assert(! stream->isSequential()); - } - bool result = open(*stream, fileName, formatParam); - return result; -} - -bool decoder::open(QIODevice& fileStream, QString& fileName, enum PixelFormat formatParam) -{ - // http://stackoverflow.com/questions/9604633/reading-a-file-located-in-memory-with-libavformat - // I think AVIOContext is the trick used to redivert the input stream - ioBuffer = (unsigned char *)av_malloc(ioBufferSize + FF_INPUT_BUFFER_PADDING_SIZE); // can get av_free()ed by libav - avioContext = avio_alloc_context(ioBuffer, ioBufferSize, 0, (void*)(&fileStream), &readFunction, NULL, &seekFunction); - container = avformat_alloc_context(); - container->pb = avioContext; - - // Open file, check usability - std::string fileNameStd = fileName.toStdString(); - if (!avtry( avformat_open_input(&container, fileNameStd.c_str(), NULL, NULL), fileNameStd )) - return false; - return openUsingInitializedContainer(formatParam); -} -*/ -// file name based method for historical continuity -bool libav::decoder::open(char* fileName, enum PixelFormat formatParam){ - - if (!avtry( avformat_open_input(&container, fileName, NULL, NULL), string(fileName) )) - return false; - return openUsingInitializedContainer(formatParam); -} -bool libav::decoder::open(string& fileName, enum PixelFormat formatParam) -{ - // Open file, check usability - - if (!avtry( avformat_open_input(&container, fileName.c_str(), NULL, NULL), fileName )) - return false; - return openUsingInitializedContainer(formatParam); -} - - -bool libav::decoder::openUsingInitializedContainer(enum PixelFormat formatParam) -{ - format = formatParam; - sc = getNumberOfChannels(); - - if (!avtry( avformat_find_stream_info(container, NULL), "Cannot find stream information." )) - return false; - if (!avtry( videoStream=av_find_best_stream(container, AVMEDIA_TYPE_VIDEO, -1, -1, &pCodec, 0), "Cannot find a video stream." )) - return false; - pCtx=container->streams[videoStream]->codec; - width = pCtx->width; - height = pCtx->height; - if (!avtry( avcodec_open2(pCtx, pCodec, NULL), "Cannot open video decoder." )) - return false; - - /* Frame rate fix for some codecs */ - if( pCtx->time_base.num > 1000 && pCtx->time_base.den == 1 ) - pCtx->time_base.den = 1000; - - /* Compute the total number of frames in the file */ - /* duration is in microsecs */ - numFrames = (int)(( container->duration / (double)AV_TIME_BASE ) * pCtx->time_base.den + 0.5); - - /* Get framebuffers */ - if (! (pRaw = avcodec_alloc_frame()) ) - throw std::runtime_error(""); - if (! (pFrameRGB = avcodec_alloc_frame()) ) - throw std::runtime_error(""); - - /* Create data buffer */ - if (format == PIX_FMT_NONE) { - numBytes = 0; - buffer = NULL; - blank = NULL; - pFrameRGB = NULL; - Sctx = NULL; - } - else { - numBytes = avpicture_get_size( format, pCtx->width, pCtx->height ); // RGB24 format - if (! (buffer = (uint8_t*)av_malloc(numBytes + FF_INPUT_BUFFER_PADDING_SIZE)) ) // RGB24 format - throw std::runtime_error(""); - if (! (blank = (uint8_t*)av_mallocz(avpicture_get_size(pCtx->pix_fmt,width,height))) ) // native codec format - throw std::runtime_error(""); - - /* Init buffers */ - avpicture_fill( (AVPicture * ) pFrameRGB, buffer, format, - pCtx->width, pCtx->height ); - - /* Init scale & convert */ - if (! (Sctx=sws_getContext( - pCtx->width, - pCtx->height, - pCtx->pix_fmt, - width, - height, - format, - SWS_POINT, // fastest? - NULL,NULL,NULL)) ) - throw std::runtime_error(""); - } - - /* Give some info on stderr about the file & stream */ - //dump_format(container, 0, fname, 0); - - previousFrameIndex = -1; - return true; -} - -bool libav::decoder::fetchFrame(int targetFrameIndex) -{ - if ((targetFrameIndex < 0) || (targetFrameIndex > numFrames)) - return false; - if (targetFrameIndex == (previousFrameIndex + 1)) { - if (! readNextFrame(targetFrameIndex)) - return false; - } - else { - int64_t response=seekToFrame(targetFrameIndex); - if (response < 0) - return false; - if (response!=targetFrameIndex){ - cerr<<"libav::decoder asked for "<streams[videoStream]->duration; - int64_t ts = av_rescale(duration,targetFrameIndex,numFrames); - int64_t tol = av_rescale(duration,1,2*numFrames); - if ( (targetFrameIndex < 0) || (targetFrameIndex >= numFrames) ) { - return -1; - } - int result = avformat_seek_file( container, //format context - videoStream,//stream id - 0, //min timestamp 0? - ts, //target timestamp - ts, //max timestamp - 0);//flags AVSEEK_FLAG_ANY //doesn't seem to work great - if (result < 0) - return -1; - - avcodec_flush_buffers(pCtx); - if (! readNextFrame(targetFrameIndex)) - return -1; - - return targetFrameIndex; -} - -bool libav::decoder::readNextFrame(int targetFrameIndex) -{ - AVPacket packet = {0}; - av_init_packet(&packet); - bool result = readNextFrameWithPacket(targetFrameIndex, packet, pRaw); - av_free_packet(&packet); - return result; -} - -// WARNING this method can raise an exception -bool libav::decoder::readNextFrameWithPacket(int targetFrameIndex, AVPacket& packet, AVFrame* pYuv) -{ - int finished = 0; - do { - finished = 0; - av_free_packet(&packet); - int result; - if (!avtry(av_read_frame( container, &packet ), "Failed to read frame")) - return false; // !!NOTE: see docs on packet.convergence_duration for proper seeking - if( packet.stream_index != videoStream ) /* Is it what we're trying to parse? */ - continue; - if (!avtry(avcodec_decode_video2( pCtx, pYuv, &finished, &packet ), "Failed to decode video")) - return false; - // handle odd cases and debug - if((pCtx->codec_id==CODEC_ID_RAWVIDEO) && !finished) - { - avpicture_fill( (AVPicture * ) pYuv, blank, pCtx->pix_fmt,width, height ); // set to blank frame - finished = 1; - } -#if 0 // very useful for debugging - cout << "Packet - pts:" << (int)packet.pts; - cout << " dts:" << (int)packet.dts; - cout << " - flag: " << packet.flags; - cout << " - finished: " << finished; - cout << " - Frame pts:" << (int)pYuv->pts; - cout << " " << (int)pYuv->best_effort_timestamp; - cout << endl; - /* printf("Packet - pts:%5d dts:%5d (%5d) - flag: %1d - finished: %3d - Frame pts:%5d %5d\n", - (int)packet.pts,(int)packet.dts, - packet.flags,finished, - (int)pYuv->pts,(int)pYuv->best_effort_timestamp); */ -#endif - if(!finished) { - if (packet.pts == AV_NOPTS_VALUE) - throw std::runtime_error(""); - if (packet.size == 0) // packet.size==0 usually means EOF - break; - } - } while ( (!finished) || (pYuv->best_effort_timestamp < targetFrameIndex)); - - av_free_packet(&packet); - - if (format != PIX_FMT_NONE) { - sws_scale(Sctx, // sws context - pYuv->data, // src slice - pYuv->linesize, // src stride - 0, // src slice origin y - pCtx->height, // src slice height - pFrameRGB->data, // dst - pFrameRGB->linesize ); // dst stride - } - - previousFrameIndex = targetFrameIndex; - return true; -} - -uint8_t libav::decoder::getPixelIntensity(int x, int y, Channel c) const -{ - return *(pFrameRGB->data[0] + y * pFrameRGB->linesize[0] + x * sc + c); -} - -int libav::decoder::getNumberOfFrames() const { return numFrames; } - -int libav::decoder::getWidth() const { return width; } - -int libav::decoder::getHeight() const { return height; } - -int libav::decoder::getNumberOfChannels() const -{ - switch(format) - { - case PIX_FMT_BGRA: - return 4; - break; - case PIX_FMT_RGB24: - return 3; - break; - case PIX_FMT_GRAY8: - return 1; - break; - default: - return 0; - break; - } - return 0; -} - -void libav::decoder::initialize() -{ - Sctx = NULL; - pRaw = NULL; - pFrameRGB = NULL; - pCtx = NULL; - container = NULL; - buffer = NULL; - blank = NULL; - pCodec = NULL; - format = PIX_FMT_NONE; - //network stuff - //reply = NULL; - //ioBuffer = NULL; - //avioContext = NULL; - maybeInitFFMpegLib(); -} - -void libav::maybeInitFFMpegLib() -{ - if (b_is_one_time_inited) - return; - av_register_all(); - avcodec_register_all(); - avformat_network_init(); - b_is_one_time_inited = true; -} - -bool libav::decoder::avtry(int result, const std::string& msg) { - if ((result < 0) && (result != AVERROR_EOF)) { - char buf[1024]; - av_strerror(result, buf, sizeof(buf)); - std::string message = std::string("libav::Error: ") + msg + buf; - //qDebug() << QString(message.c_str()); - cerr<oformat = fmt; - - fmt->video_codec = codec_id; - // fmt->video_codec = CODEC_ID_H264; // fails to write - - video_st = avformat_new_stream(container, NULL); - - pCtx = video_st->codec; - pCtx->codec_id = fmt->video_codec; - pCtx->codec_type = AVMEDIA_TYPE_VIDEO; - // resolution must be a multiple of two - pCtx->width = width; - pCtx->height = height; - - // bit_rate determines image quality - pCtx->bit_rate = width * height * 4; // ? - // pCtx->qmax = 50; // no effect? - - // "high quality" parameters from http://www.cs.ait.ac.th/~on/mplayer/pl/menc-feat-enc-libavcodec.html - // vcodec=mpeg4:mbd=2:mv0:trell:v4mv:cbp:last_pred=3:predia=2:dia=2:vmax_b_frames=2:vb_strategy=1:precmp=2:cmp=2:subcmp=2:preme=2:vme=5:naq:qns=2 - if (false) // does not help - // if (pCtx->codec_id == CODEC_ID_MPEG4) - { - pCtx->mb_decision = 2; - pCtx->last_predictor_count = 3; - pCtx->pre_dia_size = 2; - pCtx->dia_size = 2; - pCtx->max_b_frames = 2; - pCtx->b_frame_strategy = 2; - pCtx->trellis = 2; - pCtx->compression_level = 2; - pCtx->global_quality = 300; - pCtx->pre_me = 2; - pCtx->mv0_threshold = 1; - // pCtx->quantizer_noise_shaping = 2; // deprecated - // TODO - } - - pCtx->time_base = (AVRational){1, 25}; /////TODO FIX TO SUPPORT OTHER RATES - // pCtx->time_base = (AVRational){1, 10}; - pCtx->gop_size = 12; // emit one intra frame every twelve frames - // pCtx->max_b_frames = 0; - pCtx->pix_fmt = PIX_FMT_YUV420P; - if (fmt->flags & AVFMT_GLOBALHEADER) - pCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; - - if (pCtx->codec_id == CODEC_ID_H264) - { - // http://stackoverflow.com/questions/3553003/encoding-h-264-with-libavcodec-x264 - pCtx->coder_type = 1; // coder = 1 - pCtx->flags|=CODEC_FLAG_LOOP_FILTER; // flags=+loop - pCtx->me_cmp|= 1; // cmp=+chroma, where CHROMA = 1 - // pCtx->partitions|=X264_PART_I8X8+X264_PART_I4X4+X264_PART_P8X8+X264_PART_B8X8; // partitions=+parti8x8+parti4x4+partp8x8+partb8x8 - pCtx->me_method=ME_HEX; // me_method=hex - pCtx->me_subpel_quality = 7; // subq=7 - pCtx->me_range = 16; // me_range=16 - pCtx->gop_size = 250; // g=250 - pCtx->keyint_min = 25; // keyint_min=25 - pCtx->scenechange_threshold = 40; // sc_threshold=40 - pCtx->i_quant_factor = 0.71; // i_qfactor=0.71 - pCtx->b_frame_strategy = 1; // b_strategy=1 - pCtx->qcompress = 0.6; // qcomp=0.6 - pCtx->qmin = 10; // qmin=10 - pCtx->qmax = 51; // qmax=51 - pCtx->max_qdiff = 4; // qdiff=4 - pCtx->max_b_frames = 3; // bf=3 - pCtx->refs = 3; // refs=3 - // pCtx->directpred = 1; // directpred=1 - pCtx->trellis = 1; // trellis=1 - // pCtx->flags2|=CODEC_FLAG2_BPYRAMID+CODEC_FLAG2_MIXED_REFS+CODEC_FLAG2_WPRED+CODEC_FLAG2_8X8DCT+CODEC_FLAG2_FASTPSKIP; // flags2=+bpyramid+mixed_refs+wpred+dct8x8+fastpskip - // pCtx->weighted_p_pred = 2; // wpredp=2 - // libx264-main.ffpreset preset - // pCtx->flags2|=CODEC_FLAG2_8X8DCT; - // pCtx->flags2^=CODEC_FLAG2_8X8DCT; // flags2=-dct8x8 - } - - AVCodec * codec = avcodec_find_encoder(pCtx->codec_id); - if (NULL == codec) - throw std::runtime_error("Unable to find Mpeg4 codec"); - if (codec->pix_fmts) - pCtx->pix_fmt = codec->pix_fmts[0]; - { - //QMutexLocker lock(&decoder::mutex); - mutex.lock(); - if (avcodec_open2(pCtx, codec, NULL) < 0) - throw std::runtime_error("Error opening codec"); - mutex.unlock(); - } - - /* Get framebuffers */ - if (! (picture_yuv = avcodec_alloc_frame()) ) // final frame format - throw std::runtime_error(""); - if (! (picture_rgb = avcodec_alloc_frame()) ) // rgb version I can understand easily - throw std::runtime_error(""); - /* the image can be allocated by any means and av_image_alloc() is - * just the most convenient way if av_malloc() is to be used */ - if ( av_image_alloc(picture_yuv->data, picture_yuv->linesize, - pCtx->width, pCtx->height, pCtx->pix_fmt, 1) < 0 ) - throw std::runtime_error("Error allocating YUV frame buffer"); - if ( av_image_alloc(picture_rgb->data, picture_rgb->linesize, - pCtx->width, pCtx->height, PIX_FMT_RGB24, 1) < 0 ) - throw std::runtime_error("Error allocating RGB frame buffer"); - - /* Init scale & convert */ - if (! (Sctx=sws_getContext( - width, - height, - PIX_FMT_RGB24, - pCtx->width, - pCtx->height, - pCtx->pix_fmt, - SWS_BICUBIC,NULL,NULL,NULL)) ) - throw std::runtime_error(""); - -// -// -// added audio init - fmt->audio_codec = AV_CODEC_ID_MP3; - // fmt->video_codec = CODEC_ID_H264; // fails to write - - audio_st = avformat_new_stream(container, NULL); - - aCtx = audio_st->codec; - aCtx->codec_id = fmt->audio_codec; - aCtx->codec_type = AVMEDIA_TYPE_AUDIO; - - aCtx->sample_fmt=AV_SAMPLE_FMT_S16P; //s16p is invalid or not supported by aac: S16 not by mp3 - aCtx->channels=2; - aCtx->sample_rate=44100; - aCtx->channel_layout=AV_CH_LAYOUT_STEREO; - aCtx->bit_rate = 64000; - - - - AVCodec * acodec = avcodec_find_encoder(aCtx->codec_id); - mutex.lock(); - int ret = avcodec_open2(aCtx, acodec, NULL); - mutex.unlock(); - if (ret < 0) { - throw std::runtime_error("Could not open audio codec:"); - - } - - if (aCtx->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) - audio_input_frame_size = 10000; - else - audio_input_frame_size = aCtx->frame_size; //is coming out at 0? - - cerr<<"audio codec frame size is "<oformat->flags & AVFMT_GLOBALHEADER) - aCtx->flags |= CODEC_FLAG_GLOBAL_HEADER; - - - audiostep=((float)audio_input_frame_size)/(aCtx->sample_rate); - - - - -// are we supposed to use the same codeccontext? -// - - /* open the output file */ - if (!(fmt->flags & AVFMT_NOFILE)) - { - //QMutexLocker lock(&decoder::mutex); - mutex.lock(); - if (avio_open(&container->pb, file_name, AVIO_FLAG_WRITE) < 0) - throw std::runtime_error("Error opening output video file"); - mutex.unlock(); - } - avformat_write_header(container, NULL); -} - -void libav::encoder::setPixelIntensity(int x, int y, int c, uint8_t value) -{ - uint8_t * ptr = picture_rgb->data[0] + y * picture_rgb->linesize[0] + x * 3 + c; - *ptr = value; -} - -void libav::encoder::write_frame(float seconds,uint8_t *rgbdata) -{ - picture_rgb->data[0]=rgbdata; - - // convert from RGB24 to YUV - sws_scale(Sctx, // sws context - picture_rgb->data, // src slice - picture_rgb->linesize, // src stride - 0, // src slice origin y - pCtx->height, // src slice height - picture_yuv->data, // dst - picture_yuv->linesize ); // dst stride - - /* encode the image */ - // use non-deprecated avcodec_encode_video2(...) - AVPacket packet={0}; - av_init_packet(&packet); - packet.data = NULL; - packet.size = 0; - - //no time stamps as is - //http://dranger.com/ffmpeg/tutorial07.html - - picture_yuv->pts=(uint64_t)(seconds*timebase); // - - int got_packet; - int ret = avcodec_encode_video2(pCtx, - &packet, - picture_yuv, - &got_packet); - - //packet.pts=(uint64_t)(seconds*timebase); //added 0606 - packet.stream_index = video_st->index;; //added 0606 - - if (ret < 0) - throw std::runtime_error("Video encoding failed"); - if (got_packet) - { - // std::cout << "encoding frame" << std::endl; - int result = av_write_frame(container, &packet); - av_destruct_packet(&packet); - } -} -void libav::encoder::write_frame(float seconds,uint16_t *audiodata){ - audio_frame = avcodec_alloc_frame(); - AVPacket pkt = { 0 }; // data and size must be 0; - int got_packet, ret; - av_init_packet(&pkt); - audio_frame->nb_samples = audio_input_frame_size; - uint8_t *sampleptr; - int bufsize=audio_input_frame_size * av_get_bytes_per_sample(aCtx->sample_fmt) *aCtx->channels; - if (audiodata) { - sampleptr=(uint8_t*)audiodata; - } - else { - sampleptr=new uint8_t[bufsize]; - memset(sampleptr,0,bufsize); - } - - audio_frame->pts=(uint64_t)(seconds*timebase); // - - avcodec_fill_audio_frame(audio_frame, aCtx->channels, aCtx->sample_fmt, - sampleptr, - audio_input_frame_size * - av_get_bytes_per_sample(aCtx->sample_fmt) * - aCtx->channels, 0); //; - - - - ret = avcodec_encode_audio2(aCtx, &pkt, audio_frame, &got_packet); - - pkt.stream_index = audio_st->index; //hardcoded stream index added 0606 - //pkt.pts=(uint64_t)(seconds*timebase); //added 060613 - - if (!audiodata) { - delete[] sampleptr; - } - if (ret < 0) { - throw std::runtime_error("Audio encoding failed"); - } - - if (!got_packet) - return; - - // ? pkt.stream_index = st->index; - - ret = av_interleaved_write_frame(container, &pkt); - avcodec_free_frame(&audio_frame); -} - -/* virtual */ -libav::encoder::~encoder() -{ - - //avcodec_flush_buffers(pCtx); ???? from exporter version - - - int result = av_write_frame(container, NULL); // flush - result = av_write_trailer(container); - //QMutexLocker lock(&decoder::mutex); - mutex.lock(); - avio_close(container->pb); - mutex.unlock(); - - //added 0706 - video_st=nullptr; - audio_st=nullptr; - // - - for (int i = 0; i < container->nb_streams; ++i) { - av_freep(container->streams[i]); //CRASHING HERE ON STREAM 1, OUTPUT IS VALID BUT AUDIO INAUDIBLE - 060613 - } - av_free(container); - container = nullptr; - //QMutexLocker lock(&decoder::mutex); - mutex.lock(); - avcodec_close(aCtx); - avcodec_close(pCtx); - mutex.unlock(); - av_free(pCtx); - pCtx = NULL; - av_free(aCtx); - aCtx=nullptr; - av_free(picture_yuv->data[0]); - av_free(picture_yuv); - picture_yuv = NULL; - av_free(picture_rgb->data[0]); - av_free(picture_rgb); - picture_rgb = NULL; - -} - -bool libav::exporter::setup(int w,int h, int bitRate, int frameRate, std::string container){ - - maybeInitFFMpegLib(); - - this->w=w; - this->h=h; - this->bitRate=bitRate; - this->frameRate=frameRate; - this->container=container; - - return true; -} - -bool libav::exporter::record(std::string filename){ - - // allocate the output media context // - avformat_alloc_output_context2(&oc, NULL, NULL, filename.c_str()); - if (!oc) { - printf("Could not deduce output format from file extension: using MPEG.\n"); - avformat_alloc_output_context2(&oc, NULL, "mpeg", filename.c_str()); - } - if (!oc) { - return false; - } - fmt = oc->oformat; - - // Add the audio and video streams using the default format codecs - // * and initialize the codecs. // - video_st = NULL; - audio_st = NULL; - - fmt->video_codec=AV_CODEC_ID_MPEG4; - - if (fmt->video_codec != AV_CODEC_ID_NONE) { - video_st = add_stream(oc, &video_codec, fmt->video_codec); - } - if (fmt->audio_codec != AV_CODEC_ID_NONE) { - audio_st = add_stream(oc, &audio_codec, fmt->audio_codec); - } - - //set initial video params - video_st->codec->width=w; - video_st->codec->height=h; - video_st->codec->time_base.num = 1;//codecCtx->ticks_per_frame; - video_st->codec->time_base.den = frameRate; - video_st->time_base = video_st->codec->time_base; - //audioStream->time_base = codecCtx->time_base; //???has the capability of crashing - - video_st->codec->gop_size = 10; /* emit one intra frame every ten frames */ - video_st->codec->pix_fmt = PIX_FMT_YUV420P; - - // Now that all the parameters are set, we can open the audio and - // * video codecs and allocate the necessary encode buffers. // - if (video_st) - open_video(oc, video_codec, video_st); - if (audio_st) { - audioframesize=open_audio(oc, audio_codec, audio_st); - audiostep=((float)audioframesize)/(audio_st->codec->sample_rate); - std::cerr << "opened audio codec with "<flags & AVFMT_NOFILE)) { - mutex.lock(); - int ret = avio_open(&oc->pb, filename.c_str(), AVIO_FLAG_WRITE); - mutex.unlock(); - if (ret < 0) { - std::cerr <<"Could not open " << filename.c_str() << std::endl; - return false; - } - } - - // Write the stream header, if any. // - int ret = avformat_write_header(oc, NULL); - if (ret < 0) { - //std::cerr <<"Error occurred when opening output file:" << av_err2str(ret) << std::endl; - return false; - } - - if (frame) - frame->pts = 0; - - outputframe=0; - - return true; -} -bool libav::exporter::encodeFrame(unsigned char *pixels,uint16_t *samples){ - // Compute current audio and video time. // - if (audio_st) - audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; - else - audio_pts = 0.0; - - if (video_st) - video_pts = (double)video_st->pts.val * video_st->time_base.num / - video_st->time_base.den; - else - video_pts = 0.0; - - // write interleaved audio and video frames // - if (!video_st || (video_st && audio_st && audio_pts < video_pts)) { - write_audio_frame(oc, audio_st, samples); - } else { - write_video_frame(oc, video_st, pixels); - - frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base); - } - - //std::cerr << "encoded frame " << outputframe << std::endl; - outputframe++; - - return true; -} -bool libav::exporter::encodeFrame(unsigned char *pixels,AVPacket *audio){ - // Compute current audio and video time. // - if (audio_st) - audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; - else - audio_pts = 0.0; - - if (video_st) - video_pts = (double)video_st->pts.val * video_st->time_base.num / - video_st->time_base.den; - else - video_pts = 0.0; - - // write interleaved audio and video frames // - if (!video_st || (video_st && audio_st && audio_pts < video_pts)) { - write_audio_frame(oc, audio_st, audio); - } else { - write_video_frame(oc, video_st, pixels); - - frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base); - } - - //std::cerr << "encoded frame " << outputframe << std::endl; - outputframe++; - - return true; -} -bool libav::exporter::encodeFrame(unsigned char *pixels){ - video_pts = (double)video_st->pts.val * video_st->time_base.num / video_st->time_base.den; - write_video_frame(oc, video_st, pixels); - frame->pts += av_rescale_q(1, video_st->codec->time_base, video_st->time_base); - outputframe++; - return true; -} -bool libav::exporter::encodeFrame(uint16_t *samples){ - audio_pts = (double)audio_st->pts.val * audio_st->time_base.num / audio_st->time_base.den; - write_audio_frame(oc, audio_st, samples); - return true; -} -void libav::exporter::finishRecord(){ - - av_write_trailer(oc); - // Close each codec. // - if (video_st) - close_video(oc, video_st); - if (audio_st) - close_audio(oc, audio_st); - - if (!(fmt->flags & AVFMT_NOFILE)) { - // Close the output file. // - mutex.lock(); - avio_close(oc->pb); - mutex.unlock(); - } - - // free the stream // - avformat_free_context(oc); -} - -AVStream* libav::exporter::add_stream(AVFormatContext *oc, AVCodec **codec,enum AVCodecID codec_id) - { - AVCodecContext *c; - AVStream *st; - - // find the encoder // - *codec = avcodec_find_encoder(codec_id); - if (!(*codec)) { - //fprintf(stderr, "Could not find encoder for '%s'\n", - // avcodec_get_name(codec_id)); - exit(1); - } - - st = avformat_new_stream(oc, *codec); - if (!st) { - //fprintf(stderr, "Could not allocate stream\n"); - exit(1); - } - st->id = oc->nb_streams-1; - c = st->codec; - - switch ((*codec)->type) { - case AVMEDIA_TYPE_AUDIO: - st->id = 1; - c->sample_fmt = AV_SAMPLE_FMT_S16; - c->bit_rate = 64000; - c->sample_rate = 44100; - c->channels = 2; - c->channel_layout=AV_CH_LAYOUT_STEREO; - break; - - case AVMEDIA_TYPE_VIDEO: - c->codec_id = codec_id; - - c->bit_rate = 400000; - // Resolution must be a multiple of two. // - c->width = 352; - c->height = 288; - // timebase: This is the fundamental unit of time (in seconds) in terms - // * of which frame timestamps are represented. For fixed-fps content, - // * timebase should be 1/framerate and timestamp increments should be - // * identical to 1. // - c->time_base.den = frameRate; - c->time_base.num = 1; - c->gop_size = 12; // emit one intra frame every twelve frames at most // - c->pix_fmt = AV_PIX_FMT_YUV420P; //ADDED HARDCODED TJR 280513 - if (c->codec_id == AV_CODEC_ID_MPEG2VIDEO) { - // just for testing, we also add B frames // - c->max_b_frames = 2; - } - if (c->codec_id == AV_CODEC_ID_MPEG1VIDEO) { - // Needed to avoid using macroblocks in which some coeffs overflow. - // * This does not happen with normal video, it just happens here as - // * the motion of the chroma plane does not match the luma plane. // - c->mb_decision = 2; - } - break; - - default: - break; - } - - // Some formats want stream headers to be separate. // - if (oc->oformat->flags & AVFMT_GLOBALHEADER) - c->flags |= CODEC_FLAG_GLOBAL_HEADER; - - return st; - } - -void libav::exporter::open_video(AVFormatContext *oc, AVCodec *codec, AVStream *st) - { - int ret; - AVCodecContext *c = st->codec; - - // open the codec // - mutex.lock(); - ret = avcodec_open2(c, codec, NULL); - mutex.unlock(); - if (ret < 0) { - //fprintf(stderr, "Could not open video codec: %s\n", av_err2str(ret)); - exit(1); - } - - // allocate and init a re-usable frame // - frame = avcodec_alloc_frame(); - // moved to constructor and freeing in destructor -- stills crashes the same - if (!frame) { - //fprintf(stderr, "Could not allocate video frame\n"); - exit(1); - } - - // Allocate the encoded raw picture. // - ret = avpicture_alloc(&dst_picture, c->pix_fmt, c->width, c->height); - if (ret < 0) { - //fprintf(stderr, "Could not allocate picture: %s\n", av_err2str(ret)); - exit(1); - } - - // If the output format is not YUV420P, then a temporary YUV420P - // * picture is needed too. It is then converted to the required - // * output format. // - if (c->pix_fmt != AV_PIX_FMT_YUV420P) { - ret = avpicture_alloc(&src_picture, AV_PIX_FMT_RGB24, c->width, c->height); - if (ret < 0) { - //fprintf(stderr, "Could not allocate temporary picture: %s\n", - // av_err2str(ret)); - exit(1); - } - } - - // copy data and linesize picture pointers to frame // - *((AVPicture *)frame) = dst_picture; - - outPixels = (uint8_t*)av_malloc(avpicture_get_size(PIX_FMT_YUV420P, st->codec->width,st->codec->height)); - } - - int libav::exporter::open_audio(AVFormatContext *oc, AVCodec *codec, AVStream *st) - { - AVCodecContext *c; - int ret; - - c = st->codec; - - // open it // - mutex.lock(); - ret = avcodec_open2(c, codec, NULL); - mutex.unlock(); - if (ret < 0) { - //fprintf(stderr, "Could not open audio codec: %s\n", av_err2str(ret)); - exit(1); - } - - // init signal generator // - t = 0; - tincr = 2 * M_PI * 110.0 / c->sample_rate; - // increment frequency by 110 Hz per second // - tincr2 = 2 * M_PI * 110.0 / c->sample_rate / c->sample_rate; - - if (c->codec->capabilities & CODEC_CAP_VARIABLE_FRAME_SIZE) - audio_input_frame_size = 10000; - else - audio_input_frame_size = c->frame_size; - - /* - samples = av_malloc(audio_input_frame_size * - av_get_bytes_per_sample(c->sample_fmt) * - c->channels); - if (!samples) { - //fprintf(stderr, "Could not allocate audio samples buffer\n"); - exit(1); - } - */ - return audio_input_frame_size; - } - - void libav::exporter::write_audio_frame(AVFormatContext *oc, AVStream *st,uint16_t *samples) - { - AVCodecContext *c; - AVPacket pkt = { 0 }; // data and size must be 0; - AVFrame *frame = avcodec_alloc_frame(); - int got_packet, ret; - - av_init_packet(&pkt); - c = st->codec; - - //get_audio_frame(samples, audio_input_frame_size, c->channels); - frame->nb_samples = audio_input_frame_size; - uint8_t *sampleptr; - int bufsize=audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt) *c->channels; - if (samples) { - sampleptr=(uint8_t*)samples; - } - else { - sampleptr=new uint8_t[bufsize]; - memset(sampleptr,0,bufsize); - } - - avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, - sampleptr, - audio_input_frame_size * - av_get_bytes_per_sample(c->sample_fmt) * - c->channels, 0); //; - //frame->sample_rate=44100; //hard coded input rate- nope, this doesn't help - //frame->format=AV_SAMPLE_FMT_S16P; - //?? why is ffmpeg reporting fltp as the sample format??? doesn't seem to have an effect to change this though - ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet); - if (!samples) { - delete[] sampleptr; - } - if (ret < 0) { - //fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); - exit(1); - } - - if (!got_packet) - return; - - pkt.stream_index = st->index; - - // Write the compressed frame to the media file. // - ret = av_interleaved_write_frame(oc, &pkt); - if (ret != 0) { - //fprintf(stderr, "Error while writing audio frame: %s\n", - // av_err2str(ret)); - exit(1); - } - avcodec_free_frame(&frame); - } - - void libav::exporter::write_audio_frame(AVFormatContext *oc, AVStream *st,AVPacket *pkt) - { - /* - AVCodecContext *c; - AVPacket pkt = { 0 }; // data and size must be 0; - AVFrame *frame = avcodec_alloc_frame(); - int got_packet, ret; - - av_init_packet(&pkt); - c = st->codec; - - //get_audio_frame(samples, audio_input_frame_size, c->channels); - frame->nb_samples = audio_input_frame_size; - uint8_t *sampleptr; - int bufsize=audio_input_frame_size * av_get_bytes_per_sample(c->sample_fmt) *c->channels; - if (samples) { - sampleptr=(uint8_t*)samples; - } - else { - sampleptr=new uint8_t[bufsize]; - memset(sampleptr,0,bufsize); - } - avcodec_fill_audio_frame(frame, c->channels, c->sample_fmt, - sampleptr, - audio_input_frame_size * - av_get_bytes_per_sample(c->sample_fmt) * - c->channels, 1); - - ret = avcodec_encode_audio2(c, &pkt, frame, &got_packet); - if (!samples) { - free(sampleptr); - } - if (ret < 0) { - //fprintf(stderr, "Error encoding audio frame: %s\n", av_err2str(ret)); - exit(1); - } - - if (!got_packet) - return; - */ - - pkt->stream_index = st->index; - - // Write the compressed frame to the media file. // - int ret = av_interleaved_write_frame(oc, pkt); - if (ret != 0) { - //fprintf(stderr, "Error while writing audio frame: %s\n", - // av_err2str(ret)); - exit(1); - } - //avcodec_free_frame(&frame); - av_free_packet(pkt); - } - - void libav::exporter::close_audio(AVFormatContext *oc, AVStream *st) - { - mutex.lock(); - avcodec_close(st->codec); - mutex.unlock(); - - } - - void libav::exporter::write_video_frame(AVFormatContext *oc, AVStream *st, uint8_t *pixels) - { - int ret; - - AVCodecContext *c = st->codec; - -/* - if (frame_count >= STREAM_NB_FRAMES) { - // No more frames to compress. The codec has a latency of a few - // * frames if using B-frames, so we get the last frames by - // * passing the same picture again. // - } else { - if (c->pix_fmt != AV_PIX_FMT_YUV420P) { - // as we only generate a YUV420P picture, we must convert it - // * to the codec pixel format if needed // - if (!sws_ctx) { - sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_YUV420P, - c->width, c->height, c->pix_fmt, - sws_flags, NULL, NULL, NULL); - if (!sws_ctx) { - //fprintf(stderr, - // "Could not initialize the conversion context\n"); - exit(1); - } - } - fill_yuv_image(&src_picture, frame_count, c->width, c->height); - sws_scale(sws_ctx, - (const uint8_t * const *)src_picture.data, src_picture.linesize, - 0, c->height, dst_picture.data, dst_picture.linesize); - } else { - fill_yuv_image(&dst_picture, frame_count, c->width, c->height); - } - } -*/ - //always convert RGB to YUV - //should be context allocated once per render instead of per frame?? - // - // - sws_ctx = sws_getContext(c->width, c->height, AV_PIX_FMT_RGB24, - c->width, c->height, AV_PIX_FMT_YUV420P, - sws_flags, NULL, NULL, NULL); - - avpicture_fill(&src_picture, pixels, PIX_FMT_RGB24, c->width,c->height); - //avpicture_fill(&dst_picture, outPixels, PIX_FMT_YUV420P, c->width,c->height); - - sws_scale(sws_ctx, src_picture.data, src_picture.linesize, 0, c->height, dst_picture.data, dst_picture.linesize); - //fill_yuv_image(&dst_picture, frame_count, c->width, c->height); - if (oc->oformat->flags & AVFMT_RAWPICTURE) { - // Raw video case - directly store the picture in the packet // - AVPacket pkt; - av_init_packet(&pkt); - - pkt.flags |= AV_PKT_FLAG_KEY; - pkt.stream_index = st->index; - pkt.data = dst_picture.data[0]; - pkt.size = sizeof(AVPicture); - - ret = av_interleaved_write_frame(oc, &pkt); - } else { - AVPacket pkt = { 0 }; - int got_packet; - av_init_packet(&pkt); - - // encode the image // - - // 2nd time you render it crashes right after here - - // where the hell is frame being allocated? is the problem caused by it being freed? (see removeal of avframe_free in cleanup) - ret = avcodec_encode_video2(c, &pkt, frame, &got_packet); - if (ret < 0) { - //fprintf(stderr, "Error encoding video frame: %s\n", av_err2str(ret)); - exit(1); - } - // If size is zero, it means the image was buffered. // - - if (!ret && got_packet && pkt.size) { - pkt.stream_index = st->index; - - // Write the compressed frame to the media file. // - ret = av_interleaved_write_frame(oc, &pkt); - } else { - ret = 0; - } - } - - // - // added 22 may in memory leak run - // - sws_freeContext(sws_ctx); //should be done once per render instead of per frame?? - - if (ret != 0) { - //fprintf(stderr, "Error while writing video frame: %s\n", av_err2str(ret)); - exit(1); - } - frame_count++; - - //avcodec_free_frame(&frame); - } - - void libav::exporter::close_video(AVFormatContext *oc, AVStream *st) - { - mutex.lock(); - //avcodec_close(st->codec); //change 0706 to trace 2nd render issue - avcodec_close(audio_st->codec); - avcodec_close(video_st->codec); - // - // - - - //av_free(src_picture.data[0]); //removed to explore weird 2nd render crash.. seems to WORK -- seems that the picture data is owned elsewhere - av_free(dst_picture.data[0]); - av_free(frame); //removed to explore crash 2nd time render - //gives *** Error in `./rotord': corrupted double-linked list: 0x00007fd8b005bd60 *** - //where is frame initialised??? - //moved to destructor - - - av_free(outPixels); //SIGSEV here??? - mutex.unlock(); - } - -bool libav::audioloader::setup(const std::string &filename){ - - maybeInitFFMpegLib(); - - frame = avcodec_alloc_frame(); - if (!frame) - { - std::cout << "Error allocating the frame" << std::endl; - return false; - } - - formatContext = NULL; - mutex.lock(); - if (avformat_open_input(&formatContext, filename.c_str(), NULL, NULL) != 0) - { - av_free(frame); - std::cout << "Error opening the file" << std::endl; - return false; - } - mutex.unlock(); - - if (avformat_find_stream_info(formatContext, NULL) < 0) - { - mutex.lock(); - av_free(frame); - avformat_close_input(&formatContext); - mutex.unlock(); - std::cout << "Error finding the stream info" << std::endl; - return false; - } - - audioStream = NULL; - for (unsigned int i = 0; i < formatContext->nb_streams; ++i) - { - if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) - { - audioStream = formatContext->streams[i]; - break; - } - } - - if (audioStream == NULL) - { - mutex.lock(); - av_free(frame); - avformat_close_input(&formatContext); - mutex.unlock(); - std::cout << "Could not find any audio stream in the file" << std::endl; - return false; - } - - codecContext = audioStream->codec; - - codecContext->codec = avcodec_find_decoder(codecContext->codec_id); - mutex.lock(); - if (codecContext->codec == NULL) - { - - av_free(frame); - avformat_close_input(&formatContext); - std::cout << "Couldn't find a proper decoder" << std::endl; - return false; - } - else if (avcodec_open2(codecContext, codecContext->codec, NULL) != 0) - { - - av_free(frame); - avformat_close_input(&formatContext); - mutex.lock(); - std::cout << "Couldn't open the context with the decoder" << std::endl; - return false; - } - mutex.unlock(); - - av_dump_format(formatContext, 0, 0, false); //avformat.h line 1256 - int samples = ((formatContext->duration + 5000)*codecContext->sample_rate)/AV_TIME_BASE; - - std::cout << "This stream has " << codecContext->channels << " channels, a sample rate of " << codecContext->sample_rate << "Hz and "<sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ") "<index) - { - //int bytes = - avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); - - // Some frames rely on multiple packets, so we have to make sure the frame is finished before - // we can use it - } - // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory - av_free_packet(&packet); - } - return frame; - - } - AVPacket* libav::audioloader::get_packet() { - - if (!ready) return nullptr; - - int ret=av_read_frame(formatContext, &packet); - if (ret<0) { - std::cerr << "finished with code "<index) - //{ - //int bytes = - // avcodec_decode_audio4(codecContext, frame, &frameFinished, &packet); - - // Some frames rely on multiple packets, so we have to make sure the frame is finished before - // we can use it - //} - // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory - //av_free_packet(&packet);????? - //} - return &packet; - - } - uint16_t* libav::audioloader::get_samples(int num){ //presumes 16bpc here - //std::cerr << "request "<0){ - for (int i=0;inb_samples))*channels)>buffer.size()){ - int m=buffer.size(); - int s=((sample_end+std::max(num,frame->nb_samples))*channels); - buffer.reserve(s); - std::cerr << "audioloader reserved buffer to " << s << std::endl; - for (int i=m;inb_samples;i++) { - for (int j=0;jformat - //format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames, enum AVSampleFormat for audio) - int ff=frame->format; - //uint64_t frame->channel_layout - //Channel layout of the audio data. - uint64_t fcl=frame->channel_layout; - //int frame->nb_extended_buf - //Number of elements in extended_buf. - int fnb=frame->nb_extended_buf; - //int frame->decode_error_flags - //decode error flags of the frame, set to a combination of FF_DECODE_ERROR_xxx flags if the decoder produced a frame, but there were errors during the decoding. - int fde=frame->decode_error_flags; - - - //uint16_t s=((uint16_t*) frame->buf[j]->data)[i]; - uint16_t s=((uint16_t*) frame->buf[0]->data)[j*channels+i]; - //which? must be determined by format or layout of the channels - //ALSO some kind of HEINOUS memory leak?? - buffer[((sample_end+i)*frame->channels)+j]=s; - //buffer[(j*frame->channels)+(sample_end+i)]= ((uint16_t*) frame->buf[j]->data)[i]; ??planar?? nope - } - } - sample_end+=frame->nb_samples; - } - else { - for (int i=sample_end;inb_samples)*frame->channels)<num) { - sample_start=num; - } - else { - sample_start=0; - } - return (uint16_t*)(&buffer[0]); -} - -bool libav::audioloader::close() { - mutex.lock(); - av_free(frame); - avcodec_close(codecContext); - avformat_close_input(&formatContext); - mutex.unlock(); - ready=false; - sample_start=0; - sample_end=0; - return true; -} diff --git a/rotord/libavwrapper_guarded.h b/rotord/libavwrapper_guarded.h deleted file mode 100755 index faa4a2e..0000000 --- a/rotord/libavwrapper_guarded.h +++ /dev/null @@ -1,274 +0,0 @@ - #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 -#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); - 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 buffer; - AVFrame* frame; - - AVStream* audioStream; - - AVPacket packet; - int sample_end; - int sample_start; - - }; - -} - - - -#endif // libavwrapper_H diff --git a/rotord/rotord.cpp b/rotord/rotord.cpp index 27a09d7..7b7285b 100755 --- a/rotord/rotord.cpp +++ b/rotord/rotord.cpp @@ -67,26 +67,6 @@ void RotorRequestHandler::handleRequest(HTTPServerRequest& request,HTTPServerRes } -AudioAnalyserHandler::AudioAnalyserHandler(const vampHost::Settings& _settings): settings(_settings){ -} - -void AudioAnalyserHandler::handleRequest(HTTPServerRequest& request,HTTPServerResponse& response) { - - response.setChunkedTransferEncoding(true); - response.setContentType("text/html"); - - //string audioData=vampHost::runPlugin(); - - std::ostream& ostr = response.send(); - ostr << "RotorServer powered by " - "POCO C++ Libraries"; - ostr << ""; - ostr << "

"; - vampHost::runPlugin("",settings.soname,settings.filtername, "",0, settings.inputFile, ostr,true); - ostr << "

"; -} - RenderContextHandler::RenderContextHandler(const std::string _content,const HTTPServerResponse::HTTPStatus _status){ content=_content; status=_status; @@ -108,13 +88,13 @@ void RenderContextHandler::handleRequest(HTTPServerRequest& request,HTTPServerRe HTTPRequestHandler* RotorRequestHandlerFactory::createRequestHandler(const HTTPServerRequest& request){ - Application& app = Application::instance(); + Logger& logger = Logger::get("Rotor"); Poco::URI theuri=Poco::URI(request.getURI()); std::vector command; theuri.getPathSegments(command); - app.logger().information(request.clientAddress().toString()+" "+request.getMethod()); + logger.information(request.clientAddress().toString()+" "+request.getMethod()); string content=""; HTTPResponse::HTTPStatus status=HTTPResponse::HTTP_BAD_REQUEST; //by default @@ -132,7 +112,7 @@ HTTPRequestHandler* RotorRequestHandlerFactory::createRequestHandler(const HTTPS //Throws a SystemException if no MAC address can be obtained. // //seems to hang, to me - cerr << "Rotor: starting thread "<< sID << endl; + logger.information("Rotor: starting thread "+sID); manager.start(new Rotor::Render_context(sID)); content=""+sID+"\n"; status=HTTPResponse::HTTP_OK; @@ -284,6 +264,8 @@ void RotorServer::handleHelp(const std::string& name, const std::string& value){ int RotorServer::main(const std::vector& args){ if (!_helpRequested) { + + unsigned short port; xmlIO xml; diff --git a/rotord/rotord.h b/rotord/rotord.h index e9eb2a1..5b0e6ef 100755 --- a/rotord/rotord.h +++ b/rotord/rotord.h @@ -25,6 +25,15 @@ #include #include "Poco/URI.h" +#include "Poco/Channel.h" +#include "Poco/SplitterChannel.h" +#include "Poco/ConsoleChannel.h" +#include "Poco/FormattingChannel.h" +#include "Poco/FileChannel.h" +#include "Poco/Message.h" +#include "Poco/Formatter.h" +#include "Poco/PatternFormatter.h" +#include "Poco/AutoPtr.h" using Poco::Net::ServerSocket; using Poco::Net::HTTPResponse; @@ -46,6 +55,16 @@ using Poco::Util::OptionSet; using Poco::Util::OptionCallback; using Poco::Util::HelpFormatter; using Poco::Net::HTTPStreamFactory; +using Poco::Logger; +using Poco::Channel; +using Poco::SplitterChannel; +using Poco::ConsoleChannel; +using Poco::FormattingChannel; +using Poco::Formatter; +using Poco::PatternFormatter; +using Poco::FileChannel; +using Poco::Message; +using Poco::AutoPtr; #include "rotor.h" @@ -56,6 +75,7 @@ class RotorRequestHandler: public HTTPRequestHandler RotorRequestHandler(const std::string& format); void handleRequest(HTTPServerRequest& request,HTTPServerResponse& response); private: + std::string _format; }; @@ -84,6 +104,7 @@ class RotorRequestHandlerFactory: public HTTPRequestHandlerFactory public: HTTPRequestHandler* createRequestHandler(const HTTPServerRequest& request); private: + std::unordered_map context; Poco::UUIDGenerator idGen; Poco::TaskManager manager; @@ -106,6 +127,26 @@ class RotorServer: public Poco::Util::ServerApplication int main(int argc, char** argv) { + AutoPtr splitterChannel(new SplitterChannel()); + AutoPtr consoleChannel(new ConsoleChannel()); + AutoPtr fileChannel(new FileChannel("Rotord.log")); + AutoPtr rotatedFileChannel(new FileChannel("Rotord_R.log")); + + rotatedFileChannel->setProperty("rotation", "100"); + rotatedFileChannel->setProperty("archive", "timestamp"); + + splitterChannel->addChannel(consoleChannel); + splitterChannel->addChannel(fileChannel); + splitterChannel->addChannel(rotatedFileChannel); + + AutoPtr formatter(new PatternFormatter("%d-%m-%Y %H:%M:%S %s: %t")); + AutoPtr formattingChannel(new FormattingChannel(formatter, splitterChannel)); + + Logger& sLog = Logger::create("Rotor", formattingChannel, Message::PRIO_TRACE); + + Logger& logger = Logger::get("Rotor"); + logger.information("starting rendering daemon"); + HTTPStreamFactory::registerFactory(); RotorServer app; return app.run(argc, argv); -- cgit v1.2.3