summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Redfern <tim@herge.(none)>2013-04-23 14:01:06 +0100
committerTim Redfern <tim@herge.(none)>2013-04-23 14:01:06 +0100
commit1e26d66c3a7be31a9dd214b587488dfe3ed69b4b (patch)
tree036dbb6a151a6388fbfd4554cecf3469d97520f8
parent4b3aad507aaf75263f5b8c719768b24ba688c31e (diff)
writing audio but sped up for some reason
-rw-r--r--rotord/libavaudioloader.cpp45
-rw-r--r--rotord/libavaudioloader.h5
-rw-r--r--rotord/libavexporter.cpp29
-rw-r--r--rotord/libavexporter.h57
-rwxr-xr-xrotord/rotor.cpp3
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;
}