diff options
Diffstat (limited to 'rotord/rotor.cpp')
| -rw-r--r-- | rotord/rotor.cpp | 181 |
1 files changed, 69 insertions, 112 deletions
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<base_audio_processor*> 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<std::string>& //check file exists Poco::File f=Poco::File(command[3]); //std::auto_ptr<std::istream> 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<std::string>& response.status=HTTPResponse::HTTP_NOT_FOUND; response.description="<status context='"+command[1]+"'>File "+command[3]+" not found</status>\n"; } - + } else { response.status=HTTPResponse::HTTP_BAD_REQUEST; @@ -108,24 +108,20 @@ Command_response Render_context::session_command(const std::vector<std::string>& response.status=HTTPResponse::HTTP_OK; response.description="<status context='"+command[1]+"'>Rotor: analysing audio</status>\n"; char c[20]; - sprintf(c,"%02f",audio_analyser.get_progress()); + sprintf(c,"%02f",progress); response.description+="<progress>"+string(c)+"</progress>\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="<status context='"+command[1]+"'>Rotor: audio ready</status>\n"; - response.description+="<beats>"; - for (auto& i: audio_analyser.beats) { //is actually giving no data? - char c[20]; - sprintf(c,"%02f",i); - response.description+="<beat>"+string(c)+"</beat>"; - } - response.description+="\n</beats>"; - 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="<status context='"+command[1]+"'>Rotor: audio ready</status>\n"; + response.description+="<audio>\n"; + response.description+=audio_thumb->print(); + response.description+="\n</audio>"; + state=IDLE; + } } if (command[0]=="DELETE") { //for now @@ -151,7 +147,7 @@ Command_response Render_context::session_command(const std::vector<std::string>& 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="<status context='"+command[1]+"'>Rotor: loaded graph "+command[3]+"</status>\n"; @@ -241,7 +237,7 @@ Command_response Render_context::session_command(const std::vector<std::string>& response.description="<status>DUMMY RESPONSE 1</status>\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<base_audio_process //in the case of audio analysis, the daemon will pass each audio analysis object each chunk of data as it gets it //there could even be an array of audio analysis functions to perform simultaneously? //how about a vector of objects that subclass the base audio processor class? - + //1st get parameters and initialise the processors //then begin data loop locking progress variable after each frame - + // // //the example in ffmpeg works, but it isn't one that identifies a codec- it is hard coded to look for a codec for AV_CODEC_ID_MP2 //it also doesn't load through libavformat - which opens containers- it just loads a naked .mp2 stream // // - + /* av_register_all(); - + std::shared_ptr<AVFormatContext> 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,vector<base_audio_process cerr << "Rotor: Error while calling avformat_find_stream_info" << endl; return false; } - + av_dump_format(avFormat.get(), 0, 0, false); //avformat.h line 1256 - - + + AVStream* stream = nullptr; for (unsigned int i = 0; i < avFormat->nb_streams; ++i) { if (avFormat->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { @@ -324,16 +320,16 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process cerr <<"Rotor: Didn't find any audio stream in the file"<< endl; return false; } - + // getting the required codec structure const auto codec = avcodec_find_decoder(stream->codec->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<AVCodecContext> 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<base_audio_process // make sure that this vector exists as long as the avVideoCodec exists std::vector<uint8_t> codecContextExtraData; codecContextExtraData.assign(stream->codec->extradata, stream->codec->extradata + stream->codec->extradata_size); - + audioCodec->extradata = reinterpret_cast<uint8_t*>(codecContextExtraData.data()); audioCodec->extradata_size = codecContextExtraData.size(); @@ -351,23 +347,23 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process cerr <<"Rotor: Could not open codec"<< endl; return false; } - - + + //avcodec.h line 1026 - - + + Packet packet; // decoding code here //cerr << "audio codec context - sample rate: "<< audioCodec->sample_rate <<", channels: "<<audioCodec->channels<<", sample format: "<<audioCodec->sample_fmt<<endl; - + // suspect why was this in twice 210313 //do { // if (packet.packet.stream_index != stream->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> avFrame(avcodec_alloc_frame(), &av_free); @@ -375,10 +371,10 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process //Packet packet; // data in the packet of data already processed size_t offsetInData = 0; - - + + bool foundPacket=false; - + // the decoding loop, running until EOF while (true) { // reading a packet using libavformat @@ -392,20 +388,20 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process cerr << "audio codec context - sample rate: "<< audioCodec->sample_rate <<", channels: "<<audioCodec->channels<<", sample format: "<<audioCodec->sample_fmt<<endl; foundPacket=true; } - + } - - + + // preparing the packet that we will send to libavcodec AVPacket packetToSend; packetToSend.data = packet.packet.data + offsetInData; packetToSend.size = packet.packet.size - offsetInData; - + // sending data to libavcodec int isFrameAvailable = 0; //const auto processedLength = avcodec_decode_video2(avVideoCodec.get(), avFrame.get(), &isFrameAvailable, &packetToSend); - + const auto processedLength = avcodec_decode_audio4(audioCodec.get(), avFrame.get(), &isFrameAvailable, &packetToSend); //utils.c line 2018 @@ -414,16 +410,16 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process //unsigned int numberOfSamplesContainedInTheFrame = stream.frame->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 "<<processedLength<< " while processing the data"<< endl; return false; } offsetInData += processedLength; - - + + // processing the image if available if (isFrameAvailable) { // display image on the screen @@ -433,8 +429,8 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process std::this_thread::sleep(std::chrono::milliseconds(msToWait)); } */ - - + + http://www.gamedev.net/topic/624876-how-to-read-an-audio-file-with-ffmpeg-in-c/ // Initialize FFmpeg av_register_all(); @@ -455,7 +451,7 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process std::cout << "Error opening the file" << std::endl; return false; } - + if (avformat_find_stream_info(formatContext, NULL) < 0) { @@ -504,22 +500,20 @@ bool Render_context::load_audio(const string &filename,vector<base_audio_process av_dump_format(formatContext, 0, 0, false); //avformat.h line 1256 int samples = ((formatContext->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 "<<samples <<" samples" << std::endl; std::cout << "The data is in format " <<codecContext->sample_fmt<< " (aka "<< av_get_sample_fmt_name(codecContext->sample_fmt) << ") "<<std::endl; - + //we can now tell the processors the format //we can work out the number of samples at this point - - - - + for (auto p: processors) { p->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<base_audio_process // the audio data, so I won't add any junk here that might confuse you. Typically, if I want to find // documentation on an FFmpeg structure or function, I just type "<name> 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,vector<base_audio_process for (auto p: processors) { p->process_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,vector<base_audio_process av_free(frame); avcodec_close(codecContext); av_close_input_file(formatContext); - - - return true; } @@ -614,7 +609,7 @@ bool Render_context::load_graph(string &filename){ } else cerr << "Rotor: linked input " << i2 << " of node '" << nodeID << "' to node '" << fromID << "'" << endl; } - else cerr << "Rotor: linking input " << i2 << " of node: '" << nodeID << "', cannot find target '" << fromID << "'" << endl; + else cerr << "Rotor: linking input " << i2 << " of node: '" << nodeID << "', cannot find target '" << fromID << "'" << endl; } xml.popTag(); } @@ -626,44 +621,6 @@ bool Render_context::load_graph(string &filename){ } xml.popTag(); } - /* - model_name=XML.getAttribute("map4","model","none",0); - model_x=ofToFloat(XML.getAttribute("map4","x","none",0)); - model_y=ofToFloat(XML.getAttribute("map4","y","none",0)); - model_z=ofToFloat(XML.getAttribute("map4","z","none",0)); - if(XML.pushTag("map4")) { - numViews=XML.getNumTags("view"); - if(numViews) { - views=new viewpoint[numViews]; - for (int i=0;i<numViews;i++){ - XML.pushTag("view",i); - vector<string>keys; - XML.getAttributeNames("settings", keys, 0); - map<string,string>settings; - for (int k=0;k<keys.size();k++) { - settings[keys[k]]=XML.getAttribute("settings",keys[k],"none",0); - } - views[i].setup(settings); - XML.popTag(); - } - } - - numClips=XML.getNumTags("clip"); - if (numClips) { - clips=new string[numClips]; - for (int i=0;i< numClips;i++) { - XML.pushTag("clip",i); - clips[i]=XML.getAttribute("settings","file","none",0); - XML.popTag(); - } - } - - XML.popTag(); - for (int i=0;i< numClips;i++) { - printf("clip: %s\n",clips[i].c_str()); - } - } - */ return true; } else return false; @@ -675,4 +632,4 @@ Node_factory::Node_factory(){ add_type("divide",new Signal_divide()); add_type("==",new Is_new_integer()); add_type("signal_output",new Signal_output()); -}
\ No newline at end of file +} |
