summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xrotord/libavwrapper.cpp83
-rwxr-xr-xrotord/libavwrapper.h13
-rwxr-xr-xrotord/rotor.cpp27
-rwxr-xr-xrotord/rotor.h7
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: