summaryrefslogtreecommitdiff
path: root/rotord/rotor.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'rotord/rotor.cpp')
-rw-r--r--rotord/rotor.cpp124
1 files changed, 86 insertions, 38 deletions
diff --git a/rotord/rotor.cpp b/rotord/rotor.cpp
index feb4a6c..281671e 100644
--- a/rotord/rotor.cpp
+++ b/rotord/rotor.cpp
@@ -31,7 +31,8 @@ void Render_context::runTask() {
state=ANALYSING_AUDIO;
//audio_analyser.process(audio_filename);
//vampHost::runPlugin("","qm-vamp-plugins","qm-tempotracker", "",0, audio_filename, cerr,true);
- load_audio(audio_filename);
+ vector<base_audio_processor*> proc;
+ load_audio(audio_filename,proc);
state=AUDIO_READY;
}
@@ -290,42 +291,11 @@ Command_response Render_context::session_command(const std::vector<std::string>&
//YES
//http://blog.tomaka17.com/2012/03/libavcodeclibavformat-tutorial/
-
-static int open_codec_context(int *stream_idx,AVFormatContext *fmt_ctx, enum AVMediaType type)
-{
- int ret;
- AVStream *st;
- AVCodecContext *dec_ctx = NULL;
- AVCodec *dec = NULL;
- ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0);
- if (ret < 0) {
- fprintf(stderr, "Could not find %s stream in input file \n",
- av_get_media_type_string(type));
- return ret;
- } else {
- *stream_idx = ret;
- st = fmt_ctx->streams[*stream_idx];
- /* find decoder for the stream */
- dec_ctx = st->codec;
- dec = avcodec_find_decoder(dec_ctx->codec_id);
- cerr << "Looking for decoder for codec "<< dec_ctx->codec_id<<endl;
- if (!dec) {
- fprintf(stderr, "Failed to find %s codec\n",
- av_get_media_type_string(type));
- return ret;
- }
- if ((ret = avcodec_open2(dec_ctx, dec, NULL)) < 0) {
- fprintf(stderr, "Failed to open %s codec\n",
- av_get_media_type_string(type));
- return ret;
- }
- }
- return 0;
-}
+//great to use c++11 features
-bool Render_context::load_audio(string &filename){
+bool Render_context::load_audio(string &filename,vector<base_audio_processor*> processors){
//load audio data from file
//what's the best way to use this? the model is background processing, and we want to update a progress bar
//could pass a function pointer to call when each chunk of data becomes available?
@@ -341,19 +311,19 @@ bool Render_context::load_audio(string &filename){
auto avFormatPtr = avFormat.get();
if (avformat_open_input(&avFormatPtr,filename.c_str(),nullptr, nullptr) != 0) {
- cerr <<"Error while calling avformat_open_input (probably invalid file format)" << endl;
+ cerr <<"Rotor: Error while calling avformat_open_input (probably invalid file format)" << endl;
return false;
}
if (avformat_find_stream_info(avFormat.get(), nullptr) < 0) {
- cerr << "Error while calling avformat_find_stream_info" << endl;
+ cerr << "Rotor: Error while calling avformat_find_stream_info" << endl;
return false;
}
av_dump_format(avFormat.get(), 0, 0, false);
AVStream* stream = nullptr;
- for (auto i = 0; i < avFormat->nb_streams; ++i) {
+ for (unsigned int i = 0; i < avFormat->nb_streams; ++i) {
if (avFormat->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
// we've found a video stream!
stream = avFormat->streams[i];
@@ -361,11 +331,89 @@ bool Render_context::load_audio(string &filename){
}
}
if (!stream) {
- cerr <<"Didn't find any audio stream in the file"<< endl;
+ 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);
+ if (codec == nullptr) {
+ cerr <<"Rotor: Audio codec not available"<< endl;
+ return false;
+ }
+
+ // allocating a structure
+ std::shared_ptr<AVCodecContext> audioCodec(avcodec_alloc_context3(codec), [](AVCodecContext* c) { avcodec_close(c); av_free(c); });
+
+ /* extradata???
+ // we need to make a copy of videoStream->codec->extradata and give it to the context
+ // make sure that this vector exists as long as the avVideoCodec exists
+ std::vector codecContextExtraData(stream->codec->extradata, stream->codec->extradata + stream->codec->extradata_size);
+ audioCodec->extradata = reinterpret_cast(codecContextExtraData.data());
+ audioCodec->extradata_size = codecContextExtraData.size();
+
+ // initializing the structure by opening the codec
+ if (avcodec_open2(avVideoCodec.get(), codec, nullptr) < 0) {
+ cerr <<"Rotor: Could not open codec"<< endl;
+ return false;
+ }
+ */
+
+ Packet packet(avFormat.get());
+ if (packet.packet.data == nullptr) {
+ //done
+ return true;
+ }
+
+ do {
+ packet.reset(avFormat.get());
+ if (packet.packet.stream_index != stream->index)
+ continue; // the packet is not about the video 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);
+
+ // the current packet of data
+ Packet packet;
+ // data in the packet of data already processed
+ size_t offsetInData = 0;
+
+ // the decoding loop, running until EOF
+ while (true) {
+ // reading a packet using libavformat
+ if (offsetInData >= packet.packet.size) {
+ do {
+ packet.reset(avFormat.get());
+ if (packet.stream_index != videoStream->index)
+ continue;
+ } while(0);
+ }
+
+ // 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);
+ if (processedLength < 0) {
+ av_free_packet(&packet);
+ throw std::runtime_error("Error while processing the data");
+ }
+ offsetInData += processedLength;
+
+ // processing the image if available
+ if (isFrameAvailable) {
+ // display image on the screen
+
+ // sleeping until next frame
+ const auto msToWait = avVideoContext->ticks_per_frame * 1000 * avVideoContext->time_base.num / avVideoContext->time_base.den;
+ std::this_thread::sleep(std::chrono::milliseconds(msToWait));
+ }
+ }
return true;
}