diff options
Diffstat (limited to 'rotord')
| -rw-r--r-- | rotord/libavaudioloader.cpp | 45 | ||||
| -rw-r--r-- | rotord/libavaudioloader.h | 5 | ||||
| -rw-r--r-- | rotord/libavexporter.cpp | 29 | ||||
| -rw-r--r-- | rotord/libavexporter.h | 57 | ||||
| -rwxr-xr-x | rotord/rotor.cpp | 3 |
5 files changed, 128 insertions, 11 deletions
diff --git a/rotord/libavaudioloader.cpp b/rotord/libavaudioloader.cpp index 133fcd4..b842a42 100644 --- a/rotord/libavaudioloader.cpp +++ b/rotord/libavaudioloader.cpp @@ -100,6 +100,30 @@ bool libav::Audioloader::setup(const std::string &filename){ 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 "<<ret <<(ret==AVERROR_EOF?" ,EOF":"")<<std::endl; + ready=false; + return nullptr; + } + //if (packet.stream_index == audioStream->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 @@ -130,8 +154,8 @@ uint16_t* libav::Audioloader::get_samples(int num){ //presumes 16bpc here //shuffle down samples if (sample_start>0){ for (int i=0;i<sample_end-sample_start;i++){ - for (int j=0;j<frame->channels;j++) { - buffer[(i*frame->channels)+j]=buffer[((sample_start+i)*frame->channels)+j]; + for (int j=0;j<av_frame_get_channels(frame);j++) { + buffer[(i*av_frame_get_channels(frame))+j]=buffer[((sample_start+i)*av_frame_get_channels(frame))+j]; } } sample_start=sample_end-sample_start; @@ -139,18 +163,25 @@ uint16_t* libav::Audioloader::get_samples(int num){ //presumes 16bpc here sample_end=sample_start; while (sample_end<num) { frame=get_frame(); - if (((sample_end+frame->nb_samples)*frame->channels)>buffer.size()){ - buffer.reserve((sample_end+frame->nb_samples)*frame->channels); + if (((sample_end+std::max(num,frame->nb_samples))*av_frame_get_channels(frame))>buffer.size()){ + int m=buffer.size(); + int s=((sample_end+std::max(num,frame->nb_samples))*av_frame_get_channels(frame)); + buffer.reserve(s); + std::cerr << "audioloader reserved buffer to " << s << std::endl; + for (int i=m;i<s;i++) buffer.push_back(0); } if (!frame) { - for (int i=0;i<num*frame->channels;i++){ + for (int i=0;i<num*av_frame_get_channels(frame);i++){ buffer[sample_end+i]=0; } } + //std::cerr<<"filling buffer to "<<((sample_end+frame->nb_samples)*frame->channels)<<std::endl; for (int i=0;i<frame->nb_samples;i++) { - for (int j=0;j<frame->channels;j++) { - buffer[((sample_end+i)*frame->channels)+j]= ((uint16_t*) frame->buf[0])[(i*frame->channels)+j]; + for (int j=0;j<av_frame_get_channels(frame);j++) { + uint16_t s=((uint16_t*) frame->buf[j]->data)[i]; + //uint16_t s=frame->buf[j]->data[i*2]+((frame->buf[j]->data)[i*2+1]<<8); + buffer[((sample_end+i)*frame->channels)+j]= s; } } sample_end+=frame->nb_samples; diff --git a/rotord/libavaudioloader.h b/rotord/libavaudioloader.h index 5df583b..aca6bd0 100644 --- a/rotord/libavaudioloader.h +++ b/rotord/libavaudioloader.h @@ -19,6 +19,7 @@ namespace libav { bool setup(const std::string &filename); AVFrame* get_frame(); uint16_t* get_samples(int num); + AVPacket* get_packet(); bool close(); bool ready; private: @@ -32,5 +33,5 @@ namespace libav { int sample_start; }; - -}
\ No newline at end of file + +} diff --git a/rotord/libavexporter.cpp b/rotord/libavexporter.cpp index ed69cec..41238e7 100644 --- a/rotord/libavexporter.cpp +++ b/rotord/libavexporter.cpp @@ -111,6 +111,33 @@ bool libav::Exporter::encodeFrame(unsigned char *pixels,uint16_t *samples){ 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; +} void libav::Exporter::finishRecord(){ av_write_trailer(oc); @@ -126,4 +153,4 @@ void libav::Exporter::finishRecord(){ // free the stream // avformat_free_context(oc); -}
\ No newline at end of file +} diff --git a/rotord/libavexporter.h b/rotord/libavexporter.h index 9ff72d7..fd2da93 100644 --- a/rotord/libavexporter.h +++ b/rotord/libavexporter.h @@ -238,6 +238,61 @@ namespace libav { avcodec_free_frame(&frame); } + static void 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); + } + + static void close_audio(AVFormatContext *oc, AVStream *st) { avcodec_close(st->codec); @@ -417,8 +472,10 @@ namespace libav { 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); void finishRecord(); int get_audio_framesize(){return size;}; + private: AVOutputFormat *fmt; AVFormatContext *oc; diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index a7c15ba..eb86c27 100755 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -769,7 +769,7 @@ bool Video_output::render(const float duration, const float framerate,const stri int frameRate=25; AVCodecID codecId=AV_CODEC_ID_MPEG4; std::string container ="mov"; - std::string input ="01.wav"; + std::string input ="01.mp3"; bool usingaudio=audioloader.setup(input); @@ -781,6 +781,7 @@ bool Video_output::render(const float duration, const float framerate,const stri float v=0.0f; for (float f=0.0f;f<duration;f+=step) { if (!exporter->encodeFrame(get_output(Frame_spec(f,framerate,outW,outH))->RGBdata,audioloader.get_samples(exporter->get_audio_framesize()))){ + //if (!exporter->encodeFrame(get_output(Frame_spec(f,framerate,outW,outH))->RGBdata,audioloader.get_packet())){ cerr << "Rotor: video output failed"<<endl; break; } |
