diff options
| -rwxr-xr-x | rotord/libavwrapper.cpp | 83 | ||||
| -rwxr-xr-x | rotord/libavwrapper.h | 13 | ||||
| -rwxr-xr-x | rotord/rotor.cpp | 27 | ||||
| -rwxr-xr-x | rotord/rotor.h | 7 |
4 files changed, 109 insertions, 21 deletions
diff --git a/rotord/libavwrapper.cpp b/rotord/libavwrapper.cpp index 5cff8c9..1fe054e 100755 --- a/rotord/libavwrapper.cpp +++ b/rotord/libavwrapper.cpp @@ -368,7 +368,7 @@ bool libav::decoder::fetchFrame(int targetFrameIndex) if (response < 0) return false; if (response!=targetFrameIndex){ - cerr<<"libav::decoder asked for "<<targetFrameIndex<<", got "<<response<<endl; + cerr<<"libav::decoder asked for "<<targetFrameIndex<<", got "<<response<<endl; //does not seem to be aware of wrong frame } } previousFrameIndex = targetFrameIndex; @@ -386,10 +386,10 @@ int libav::decoder::seekToFrame(int targetFrameIndex) } int result = avformat_seek_file( container, //format context videoStream,//stream id - 0, //min timestamp + 0, //min timestamp 0? ts, //target timestamp ts, //max timestamp - 0); //AVSEEK_FLAG_ANY),//flags + 0);//flags AVSEEK_FLAG_ANY //doesn't seem to work great if (result < 0) return -1; @@ -546,11 +546,14 @@ bool libav::decoder::b_is_one_time_inited = false; /////////////////////////// -libav::encoder::encoder(const char * file_name, int width, int height, enum AVCodecID codec_id) +libav::encoder::encoder(const char * file_name, int width, int height, float _framerate,enum AVCodecID codec_id) : picture_yuv(NULL) , picture_rgb(NULL) , container(NULL) { + //multiply float seconds by this to get pts + timebase=((float)AV_TIME_BASE_Q.den)/(AV_TIME_BASE_Q.num*_framerate*3.125f); //no idea where the 3.125 comes from + if (0 != (width % 2)) cerr << "WARNING: Video width is not a multiple of 2" << endl; if (0 != (height % 2)) @@ -605,7 +608,7 @@ libav::encoder::encoder(const char * file_name, int width, int height, enum AVCo // TODO } - pCtx->time_base = (AVRational){1, 25}; + 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; @@ -679,6 +682,27 @@ libav::encoder::encoder(const char * file_name, int width, int height, enum AVCo 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)) { @@ -695,8 +719,10 @@ void libav::encoder::setPixelIntensity(int x, int y, int c, uint8_t value) *ptr = value; } -void libav::encoder::write_frame() +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 @@ -713,6 +739,11 @@ void libav::encoder::write_frame() 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, @@ -727,6 +758,46 @@ void libav::encoder::write_frame() 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() diff --git a/rotord/libavwrapper.h b/rotord/libavwrapper.h index 449c2f2..c06a94d 100755 --- a/rotord/libavwrapper.h +++ b/rotord/libavwrapper.h @@ -131,18 +131,27 @@ namespace libav { public: //typedef encoder::Channel Channel; - encoder(const char * file_name, int width, int height, enum AVCodecID codec_id = CODEC_ID_MPEG4); + 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(); + 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; }; + } diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index 83a3b8f..bd1ace9 100755 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -194,10 +194,11 @@ bool Video_output::render(const float duration, const float framerate,const stri float spct=100.0f/duration; - if (exporter->setup(outW,outH,bitRate,frameRate,container)) { //codecId, - if (exporter->record(output_filename)) { + //if (exporter->setup(outW,outH,bitRate,frameRate,container)) { //codecId, + // if (exporter->record(output_filename)) { + libav::encoder encoder=libav::encoder(output_filename.c_str(),outW,outH,framerate); - cerr << "Rotor: Video_output rendering " << duration << " seconds at " << framerate << " fps, audio frame size: " << exporter->get_audio_framesize()<<endl; + //cerr << "Rotor: Video_output rendering " << duration << " seconds at " << framerate << " fps, audio frame size: " << exporter->get_audio_framesize()<<endl; //25fps video and 43.06640625fps audio? hmm //how to get the timecodes correct for the interleaved files @@ -206,25 +207,31 @@ bool Video_output::render(const float duration, const float framerate,const stri float vf=0.0f; float af=0.0f; while (vf<duration-vstep) { - while (fless(vf,af)) { + while (!fless(af,vf)) { //insert audio frames until we are ahead of the video - exporter->encodeFrame(audioloader.get_samples(exporter->get_audio_framesize())); - af+=exporter->get_audio_step(); + //exporter->encodeFrame(audioloader.get_samples(exporter->get_audio_framesize())); + //af+=exporter->get_audio_step(); + uint16_t *s=audioloader.get_samples(encoder.get_audio_framesize()); + encoder.write_frame(af,s); //crashes + af+=encoder.get_audio_step(); } Image* i=get_output(Frame_spec(vf,framerate,duration,outW,outH)); if (i) { - exporter->encodeFrame(i->RGBdata); + //exporter->encodeFrame(i->RGBdata); + + //encoder->picture_rgb.pts=; + encoder.write_frame(vf,i->RGBdata); } vf+=vstep; progress=vf/duration; } - exporter->finishRecord(); + //exporter->finishRecord(); cerr << "Rotor: Video_output finished "<< endl; return true; - } - } + // } + //} return false; } diff --git a/rotord/rotor.h b/rotord/rotor.h index 6984157..4f94151 100755 --- a/rotord/rotor.h +++ b/rotord/rotor.h @@ -686,9 +686,9 @@ namespace Rotor { Video_output(){}; Video_output(map<string,string> &settings) { base_settings(settings); - exporter=new libav::Exporter(); + //exporter=new libav::Exporter(); }; - ~Video_output(){ delete exporter; }; + ~Video_output(){ /*delete exporter;*/ }; Image *output(const Frame_spec &frame){ if (image_inputs[0]->connection) { return ((Image_node*)(image_inputs[0]->connection))->get_output(frame); @@ -700,8 +700,9 @@ namespace Rotor { private: //ofxMovieExporter *exporter; - libav::Exporter *exporter; + //libav::Exporter *exporter; libav::Audioloader audioloader; + //libav::encoder encoder; }; class Video_loader: public Image_node { public: |
