From 7cf0551b85deed68d0eefd51e7b233e5c488f63b Mon Sep 17 00:00:00 2001 From: Tim Redfern Date: Tue, 26 Mar 2013 18:33:54 +0000 Subject: nearly working thumbnailer --- rotord/rotor.cpp | 181 +++++++++++++++++++++---------------------------------- 1 file changed, 69 insertions(+), 112 deletions(-) (limited to 'rotord/rotor.cpp') diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp index de9f4ea..85382ea 100644 --- a/rotord/rotor.cpp +++ b/rotord/rotor.cpp @@ -6,7 +6,7 @@ bool fequal(const float u,const float v){ if (abs(u-v)<.001) return true; else return false; }; - + using namespace Rotor; @@ -17,7 +17,7 @@ using namespace Rotor; string output=""; int outputNo=0; */ - + void Render_context::runTask() { while (!isCancelled()) { int cmd=0; @@ -32,7 +32,7 @@ void Render_context::runTask() { //audio_analyser.process(audio_filename); //vampHost::runPlugin("","qm-vamp-plugins","qm-tempotracker", "",0, audio_filename, cerr,true); vector proc; - proc.push_back(new audio_thumbnailer()); + proc.push_back(audio_thumb); if (load_audio(audio_filename,proc)) { state=AUDIO_READY; //set the response @@ -83,8 +83,8 @@ Command_response Render_context::session_command(const std::vector& //check file exists Poco::File f=Poco::File(command[3]); //std::auto_ptr pStr(URIStreamOpener::defaultOpener().open(command[3])); - - + + if (f.exists()) { //pass to worker thread ??if engine is ready?? ??what if engine has finished but results aren't read?? audio_filename=command[3]; //for now, store session variables in memory @@ -95,7 +95,7 @@ Command_response Render_context::session_command(const std::vector& response.status=HTTPResponse::HTTP_NOT_FOUND; response.description="File "+command[3]+" not found\n"; } - + } else { response.status=HTTPResponse::HTTP_BAD_REQUEST; @@ -108,24 +108,20 @@ Command_response Render_context::session_command(const std::vector& response.status=HTTPResponse::HTTP_OK; response.description="Rotor: analysing audio\n"; char c[20]; - sprintf(c,"%02f",audio_analyser.get_progress()); + sprintf(c,"%02f",progress); response.description+=""+string(c)+"\n"; } - if (state==AUDIO_READY) { - //not sure about this-- should this state be retained? - //can the data only be read once? - //for now - response.status=HTTPResponse::HTTP_OK; - response.description="Rotor: audio ready\n"; - response.description+=""; - for (auto& i: audio_analyser.beats) { //is actually giving no data? - char c[20]; - sprintf(c,"%02f",i); - response.description+=""+string(c)+""; - } - response.description+="\n"; - state=IDLE; - } + if (state==AUDIO_READY) { + //not sure about this-- should this state be retained? + //can the data only be read once? + //for now + response.status=HTTPResponse::HTTP_OK; + response.description="Rotor: audio ready\n"; + response.description+=""; + state=IDLE; + } } if (command[0]=="DELETE") { //for now @@ -151,7 +147,7 @@ Command_response Render_context::session_command(const std::vector& if (state==IDLE) { //eventually not like this Poco::File f=Poco::File(command[3]); if (f.exists()) { - string graph_filename=command[3]; + string graph_filename=command[3]; if (load_graph(graph_filename)) { response.status=HTTPResponse::HTTP_OK; //response.description="Rotor: loaded graph "+command[3]+"\n"; @@ -241,7 +237,7 @@ Command_response Render_context::session_command(const std::vector& response.description="DUMMY RESPONSE 1\n"; response.status=HTTPResponse::HTTP_OK; } - + } if (command[2]=="render") { if (command[0]=="GET") { @@ -281,22 +277,22 @@ bool Render_context::load_audio(const string &filename,vector avFormat(avformat_alloc_context(), &avformat_free_context); - + auto avFormatPtr = avFormat.get(); if (avformat_open_input(&avFormatPtr,filename.c_str(),nullptr, nullptr) != 0) { cerr <<"Rotor: Error while calling avformat_open_input (probably invalid file format)" << endl; @@ -307,11 +303,11 @@ bool Render_context::load_audio(const string &filename,vectornb_streams; ++i) { if (avFormat->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -324,16 +320,16 @@ bool Render_context::load_audio(const string &filename,vectorcodec->codec_id); //returns AVCodec* if (codec == nullptr) { cerr <<"Rotor: Audio codec not available"<< endl; return false; } - - //AVCodecContext?? avFormat->streams[i]->codec - + + //AVCodecContext?? avFormat->streams[i]->codec + // allocating a structure std::shared_ptr audioCodec(avcodec_alloc_context3(codec), [](AVCodecContext* c) { avcodec_close(c); av_free(c); }); @@ -342,7 +338,7 @@ bool Render_context::load_audio(const string &filename,vector codecContextExtraData; codecContextExtraData.assign(stream->codec->extradata, stream->codec->extradata + stream->codec->extradata_size); - + audioCodec->extradata = reinterpret_cast(codecContextExtraData.data()); audioCodec->extradata_size = codecContextExtraData.size(); @@ -351,23 +347,23 @@ bool Render_context::load_audio(const string &filename,vectorsample_rate <<", channels: "<channels<<", sample format: "<sample_fmt<index) /// continue; // the packet is not about the stream we want, let's jump again the start of the loop //} while(0); // - + // allocating an AVFrame std::shared_ptr avFrame(avcodec_alloc_frame(), &av_free); @@ -375,10 +371,10 @@ bool Render_context::load_audio(const string &filename,vectorsample_rate <<", channels: "<channels<<", sample format: "<sample_fmt<nb_samples * stream.codecContext->channels; //unsigned int numberOfSamplesToPlayPerSecond = stream.codecContext->sample_rate; // usually 44100 or 48000 //const void* data = stream.frame->data[0]; - - + + if (processedLength < 0) { //av_free_packet(&packet); shouldn't have to because of type safe wrapper cerr <<"Error "<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) << ") "<init(codecContext->channels,16,samples); } AVPacket packet; av_init_packet(&packet); + int sample_processed=0; // Read the packets in a loop while (av_read_frame(formatContext, &packet) == 0) @@ -541,18 +535,19 @@ bool Render_context::load_audio(const string &filename,vector doxygen" into google (like // "AVFrame doxygen" for AVFrame's docs) - + //std::cout << "Got a frame: bytes " << bytes << std::endl; //now we can pass the data to the processor(s) for (auto p: processors) { - p->process_frame(frame->data[0],frame->nb_samples); + sample_processed=p->process_frame(frame->data[0],frame->nb_samples); } - + mutex.lock(); + progress=((double)sample_processed)/samples; + mutex.unlock(); } } - // You *must* call av_free_packet() after each call to av_read_frame() or else you'll leak memory - av_free_packet(&packet); + av_free_packet(&packet); //crashes here!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! SIGSEV In _int_free (av=0xb4600010, p=0xb46025c8, have_lock=0) at malloc.c:4085 () } // Some codecs will cause frames to be buffered up in the decoding process. If the CODEC_CAP_DELAY flag @@ -568,6 +563,9 @@ bool Render_context::load_audio(const string &filename,vectorprocess_frame(frame->data[0],frame->nb_samples); } + mutex.lock(); + progress=((double)sample_processed)/samples; + mutex.unlock(); } } @@ -575,9 +573,6 @@ bool Render_context::load_audio(const string &filename,vectorkeys; - XML.getAttributeNames("settings", keys, 0); - mapsettings; - for (int k=0;k